feat: build system transition to release fork + archive hardening
Release fork infrastructure: - REDBEAR_RELEASE=0.1.1 with offline enforcement (fetch/distclean/unfetch blocked) - 195 BLAKE3-verified source archives in standard format - Atomic provisioning via provision-release.sh (staging + .complete sentry) - 5-phase improvement plan: restore format auto-detection, source tree validation (validate-source-trees.py), archive-map.json, REPO_BINARY fallback Archive normalization: - Removed 87 duplicate/unversioned archives from shared pool - Regenerated all archives in consistent format with source/ + recipe.toml - BLAKE3SUMS and manifest.json generated from stable tarball set Patch management: - verify-patches.sh: pre-sync dry-run report (OK/REVERSED/CONFLICT) - 121 upstream-absorbed patches moved to absorbed/ directories - 43 active patches verified clean against rebased sources - Stress test: base updated to upstream HEAD, relibc reset and patched Compilation fixes: - relibc: Vec imports in redox-rt (proc.rs, lib.rs, sys.rs) - relibc: unsafe from_raw_parts in mod.rs (2024 edition) - fetch.rs: rev comparison handles short/full hash prefixes - kibi recipe: corrected rev mismatch New scripts: restore-sources.sh, provision-release.sh, verify-sources-archived.sh, check-upstream-releases.sh, validate-source-trees.py, verify-patches.sh, repair-archive-format.sh, generate-manifest.py Documentation: AGENTS.md, README.md, local/AGENTS.md updated for release fork model
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
a31ebd5556523f41a65224633177608303909d2ee332a67d2dfa39868915606a archives-zstd.tar.gz
|
||||
ea059a7222b0b79f1d4224fe844940e2bd5362247df94854f57bcf64b7fd3eb5 archives-zstd-v1.5.7-patched.tar.gz
|
||||
3ee6d3d961b7671a3a7978222fd2d124934a2047797bbb3341438b2251d50ef0 branding-redbear-release-vunknown-patched.tar.gz
|
||||
61983d26e05966da0a5e0abb0d68f719521aa416fd3aeadd8b93a8304fc84a60 core-base-initfs.tar.gz
|
||||
3674a72d65977c03422127fee2b961ff1997f0854ad44f1651410840d37152ab core-base-initfs-v463f76b9-patched.tar.gz
|
||||
61983d26e05966da0a5e0abb0d68f719521aa416fd3aeadd8b93a8304fc84a60 core-base.tar.gz
|
||||
1415356f8557f1f3b5568eff10fcb99f87c754fcad254cde72caf003282270e7 core-base-v463f76b9-patched.tar.gz
|
||||
aca55a89de555eb722bd002ab3f707e964001b9e2b62ca32168feda3ab94672f core-base-v463f76b-patched.tar.gz
|
||||
76695e0ee48f379ff4301769e1587a5239c60b7796760c1d24b3925198a31dea core-bootloader.tar.gz
|
||||
5af476ccd1bc93c89d0c650a57a17fd98b4bb2a4d2ad4af8b50b3f24523ed87b core-bootloader-vb22a35c-patched.tar.gz
|
||||
e5652eaf14965efeaebd0aba5d6ddd205ba3308567693ddc93592ab9c32e4620 core-coreutils.tar.gz
|
||||
ce33a62697205ee82ca1d7c4ce07fe5031307f8034d20851f4ee2ea49887e4ce core-coreutils-v5559e20-patched.tar.gz
|
||||
19be72b52f4595797ecc72337dfad208a21e0765feff8768e653748de6033ae4 core-ext4d.tar.gz
|
||||
f2906b6101db9842c6618978d97026ae6dbc9791c7410a98db84500787ded5b2 core-ext4d-vunknown-patched.tar.gz
|
||||
9bc43eb5601d4f7d7a4bfed5b2743f2c48b9fb60ad2b1ebf41aec32ad7c0d8b1 core-extrautils.tar.gz
|
||||
4346bdabe83b31fe4adf7cbddfa6674ec7b31f20bc25c7d8c6c5aebdd8e5b571 core-extrautils-vfb66941-patched.tar.gz
|
||||
ec501aa5fd302e853befd2119a44f4040d3dda09c0e704949c39d507d52354e9 core-fatd.tar.gz
|
||||
cf45041abc4d198467091cdc16d5d8375b2545521dc986130f01abd46f8e0c6d core-fatd-vunknown-patched.tar.gz
|
||||
cc4e08580e1d2ea4f4d98fd17f17c03894984ca166b6cb6ab6c38946c2301a07 core-findutils.tar.gz
|
||||
fedfb7851f7bfcbf75e4980b04ed59d4ac524f9d9a3b73786b6e5469c876962b core-findutils-v116c044-patched.tar.gz
|
||||
c59f3bec37b179df5e895de1fa726a0b27c7979f6c9d023e1167db1443bad9b7 core-grub-v2.12-patched.tar.gz
|
||||
844ddbc8c107f2d7626f14303092aa40468c439e23c1a2aeaca77e520cbd51cb core-installer.tar.gz
|
||||
a791231835630e84da0f4fd45f4d39d7e1ae92a877baa3756ca4d4bddca98273 core-installer-v948bfdc-patched.tar.gz
|
||||
54c14322d0aa2dba5077fcfbb35b83f3b818411e2b65f38857fc4c8cf040b8b3 core-ion.tar.gz
|
||||
dfc55adc306c136ddc4d754256e2d2f1474c4c44e5e40da1ae03faa32f4684fb core-ion-v1440704f-patched.tar.gz
|
||||
b65b124363fda03508fa2aebb0b0bc1351a3cea0af6cb53c123487c6e5688e36 core-kernel-v866dfad-patched.tar.gz
|
||||
c5f66c8e0c47bde679b2d2e3f6d4f4d9b7072925dd3923664f9b057743bd54e4 core-netdb.tar.gz
|
||||
cf4dc0636fe527815efe23a7c4004728d43d56ca07fab785170dca39b2ca700d core-netdb-v2c15606-patched.tar.gz
|
||||
e036b781f0e5570d2c9ed99a0bf38468fd4322409bc6f2bbc8e1108debd915cc core-netutils.tar.gz
|
||||
0724f5e41c8c5cdeaae8e1c23eef2832f05ae2b94e7ef96bfff8d2178bcc174c core-netutils-v40a573b-patched.tar.gz
|
||||
5a7f70553dd588fa65332e12cc21ce59de3dc05dbac73064dad70d29e0e26511 core-pkgutils.tar.gz
|
||||
787557d5430033d0eed827e029a23f56439c4c76bc12f639c32245fccaec3f9b core-pkgutils-v70c5067-patched.tar.gz
|
||||
889dd144e5d6c8a90da00d83545686ae3ac0a1258f5e092bcd1c3e0cd26c4371 core-redoxfs.tar.gz
|
||||
a9886db5a6b2ff5ce2fd1ad3167b1a6c1fdf509c819ccaf9d59e439370621ece core-redoxfs-vb596776-patched.tar.gz
|
||||
67d6cfb8eb3f7164212858cd27f49e950e1b7fc00ac03bd7a6af738a735af0c2 core-relibc-v861bbb0-patched.tar.gz
|
||||
7203243b8bf1eb0d2f24dce55e31e16229a817ef14c372a1b9b88653d3896d91 core-userutils.tar.gz
|
||||
14e7288f3cc7ae01c60c2a3ceef634dcc1c7dda87f5d88fec1624bb122138cef core-userutils-v0c5274f-patched.tar.gz
|
||||
87f09948dde5800459bd92b242391dcfc0684d91a6590318a06be354d8e7c3c2 core-uutils.tar.gz
|
||||
501572a66e107bc4ae07d0336d09d59da475bcc36c688487fac2d06c384ffeb7 core-uutils-v1f7c81f-patched.tar.gz
|
||||
3bb4b54cc021f5b4633d8d36d16c808911d7de2590172b3768fe9d0c7eecbd39 dev-cmake-v4.0.3-patched.tar.gz
|
||||
ee26032e11572ddfc35010b6bc2fc26a069ceda6ec01293be103fa7006d7c1e7 dev-gcc13-v8e365ce7e5-patched.tar.gz
|
||||
59ed3971c39dee06327da06a92545e4f70eddbbdc4ebf73fc7e075e1ee046dd4 dev-git.tar.gz
|
||||
230a1a25c1b3d3782ac61eedd900052b075b055a944ce4cdec356ffb779410d5 dev-git-v2.13.1-patched.tar.gz
|
||||
0cb8eaec77c01c7668f8ac13656a252cdee92f97ff24f9cfd9cb39125e8e2b5a dev-llvm21.tar.gz
|
||||
a508f9987095a8a45428763a6b7d74ad8852a89d46c4696fec7bb671ba02d846 dev-llvm21-v250d0b022e-patched.tar.gz
|
||||
e046d500a60a3266dd04b63b92b85cbba3ddfc76c1d163e7f63e015e4162badc dev-pciids.tar.gz
|
||||
7c65ff91a06b0c30759ca657f6652b4c4a0e6cc4da7ff939715359eb1af49549 dev-pciids-vfae84a8-patched.tar.gz
|
||||
1af52b8b8bcd2f04626db16a491f5285ac8b9a2354c6e7c28ad57cf46fb82a26 download-curl-vf50c28394-patched.tar.gz
|
||||
02b7f74d6149e3eea2e1e069f61595ae0943328cd5906f1dd84b407f26ab41d1 drivers-linux-kpi.tar.gz
|
||||
c1dad118b2fa2d477b4a6540225ca4278a869667aeca8fb05cbf1887987709b0 drivers-linux-kpi-vunknown-patched.tar.gz
|
||||
9a00ac5a5576b2699d5b0613010853614aafdc9fc2e6ce6e0ba72c4164624c7f drivers-redbear-btusb.tar.gz
|
||||
ae5ea46a07572ca35f2df89650fd15f6637e7a5893ea20300ebae967b4b9b275 drivers-redbear-btusb-vunknown-patched.tar.gz
|
||||
b1fc69a7fdf3b0556165207531429adc47eff7aac9cc80d2ec87777d1ab71104 drivers-redbear-iwlwifi.tar.gz
|
||||
0bfbc2d093b829d1f2ba2e1eefa55a88198525d08daa91bcdf475c306bbbc6bd drivers-redbear-iwlwifi-vunknown-patched.tar.gz
|
||||
95899472009b85ba2b29fdc77e7ebdad926f81c86d071ca1c4f56b3e4617501c drivers-redox-driver-sys.tar.gz
|
||||
bddd6f7c4f48ecfcc0f91644da1a4f3e796225fcb2595b6fee44006c0ff4afa9 drivers-redox-driver-sys-vunknown-patched.tar.gz
|
||||
7c51a7d0bbe6871c0199bde1527d455662b6c8430c061470a4962084b373ad26 files-mc-v4.8.33-patched.tar.gz
|
||||
1372f921f5d095953d20e253662881cc2ba51ee8eda9c7ebcc24388ffc30c527 fonts-dejavu-v2.37-patched.tar.gz
|
||||
031881eb827deb0c545bef5d8ebc7f1c4c2989dc0ab67972ac33d288821acdaa fonts-freefont-vunknown-patched.tar.gz
|
||||
5d31b6dbcf47f2c8626c9d6efbbcfd3246a2589e36f92c54dbd62cf5c83b148d fuse-e2fsprogs-v1.47.1-patched.tar.gz
|
||||
97313c39dac45eca01dd46c96813473e426a99fe91d5971ad56b9bab53106063 gpu-amdgpu-vunknown-patched.tar.gz
|
||||
dd64e143ca81e3d8a8935f9a8421c66f2dfe4e774ef0d57a8799f670dc20cf55 gpu-redox-drm.tar.gz
|
||||
aaec2ebff059ed9a23a11d9b333c130b5bbfaaeb68b14d270a6279120de86c2a gpu-redox-drm-vunknown-patched.tar.gz
|
||||
d4f6e46eb431869b728a0d9ae8e9a9690bb635755a5b0ff6a7c34bdc08a54429 icons-hicolor-icon-theme.tar.gz
|
||||
adcc4573c1ef28ec48b497d59b7d92865c7086a1269c6082038356e3fb8cf10a icons-hicolor-icon-theme-v8d22bbf-patched.tar.gz
|
||||
6a7c47b0f20e3d391aead41bc5a097aaf4bb95c3e74e2f32be3f8439bc71a5a7 icons-pop-icon-theme.tar.gz
|
||||
1d1b966a61a02458662d8ae7ad40fc662d80e3ac2c91f8e01d4f7b2d31e2022d icons-pop-icon-theme-v1a575a8-patched.tar.gz
|
||||
894cccef17471956656757a8e6eec4b6b85d1b66568f08b61b95cbb3b375b92e kde-kdecoration-v6.3.4-patched.tar.gz
|
||||
ee62bf2441e9763e4cde26c0dbf980425e595663fc412da56c7f338d89020cf1 kde-kf6-attica-v6.10.0-patched.tar.gz
|
||||
1b4667ac737250698eb5406d0b06476b048821e0f9aced7fa2a7f6f3ab69fb6f kde-kf6-extra-cmake-modules-v6.10.0-patched.tar.gz
|
||||
9e109258bec7005d63ef4f547957105e989848f7d66d559af24645460e096aff kde-kf6-karchive-v6.10.0-patched.tar.gz
|
||||
00e72e346159e3ca9a236b6fa13b840f347e2997e11d83f762ca4c7fa789745c kde-kf6-kauth-v6.10.0-patched.tar.gz
|
||||
37be8a15b00a623d546e14ae4f34d8c8a6a8f4941edc81ce7d04fa06b601b78d kde-kf6-kbookmarks-v6.10.0-patched.tar.gz
|
||||
682291f3bdc84c9c78b8f20546d681773766381934f3db58e353bf7320801402 kde-kf6-kcmutils-v6.10.0-patched.tar.gz
|
||||
a20c7cc62c5e80206625feecf7719a90884a5cb5a97b00e08751f5588362643b kde-kf6-kcodecs-v6.10.0-patched.tar.gz
|
||||
ea9bf7bfcabf062b16be1b7d29571762591cb785bdc6b247e84497c9cc46bd13 kde-kf6-kcolorscheme-v6.10.0-patched.tar.gz
|
||||
ae69e3d4f04760acc209deef12d27acb729fb11c1e3a070d3ddd036f073c8878 kde-kf6-kcompletion-v6.10.0-patched.tar.gz
|
||||
8c2a7e62c5170ceca56fff639aeaa404aa73f4916c64cd8a54081fcc1318ce8b kde-kf6-kconfig-v6.10.0-patched.tar.gz
|
||||
e726a54383744a6e90f4de558a8b7962c1f6d658a8848df18e49da0748342b81 kde-kf6-kconfigwidgets-v6.10.0-patched.tar.gz
|
||||
f31f1a855b7c8952f3afc067f6fbc968e8d6ddb8bf8997830d72d937aa738603 kde-kf6-kcoreaddons-v6.10.0-patched.tar.gz
|
||||
9fec6ce5988b055c530b1f5a2bcea096dcacd85c56781c51086a93213965a0e0 kde-kf6-kcrash-v6.10.0-patched.tar.gz
|
||||
6ca5d940920a86c79ac96d09d42bf1245bd99301fb50deca65f6dd509f312f01 kde-kf6-kdbusaddons-v6.10.0-patched.tar.gz
|
||||
217fa5a3088fe2974f0b69db48adde58fe85234a2275510ce09aea028dc59360 kde-kf6-kdeclarative-v6.10.0-patched.tar.gz
|
||||
8aa9c0df4e7383af69da6a0adc670728365270074c9b838f46760a31f6ab1ac9 kde-kf6-kded6-v6.10.0-patched.tar.gz
|
||||
21c2f0e2282e499e0915023b19c9d7be74bd80c2450de2157667c17832107200 kde-kf6-kglobalaccel-v6.10.0-patched.tar.gz
|
||||
955c1a31361812c65cadcf903d631335413073ac1bc52317c996cf808e5b992f kde-kf6-kguiaddons-v6.10.0-patched.tar.gz
|
||||
b123dcdd8aa0a4cf66aaef6dc12d3ac1f4e77d5139f1d07fe76b89ae0400eb3a kde-kf6-ki18n-v6.10.0-patched.tar.gz
|
||||
d81ec6333c08ebd850843888942aaea884bbe6cff682b974004195781762db03 kde-kf6-kiconthemes-v6.10.0-patched.tar.gz
|
||||
3aff2490c3d354f052ad1d536ac1e05d0c78a710946c652f568ea2287d91651c kde-kf6-kidletime-v6.10.0-patched.tar.gz
|
||||
ee1281eaaafc1e3966387292a9cfb36930c5c610a98cee8dddec0a7a1674b218 kde-kf6-kio-v6.10.0-patched.tar.gz
|
||||
05a9d9f1b3469cd369a5f5d9c336232338529c4161298cb64dbc5fab253ad4e5 kde-kf6-kitemmodels-v6.10.0-patched.tar.gz
|
||||
ab0623ff7695e1f99367f592f59d81d856164d3f4727a0473ab761a36c4e2737 kde-kf6-kitemviews-v6.10.0-patched.tar.gz
|
||||
4cf81e73c14f24ee4adc8c909d4475e9f43e7f1d7e6b0d91ab23ce2c55514248 kde-kf6-kjobwidgets-v6.10.0-patched.tar.gz
|
||||
94d02004033a2f718abefb164d7126b48cd7795ff523318372568f7608d706fe kde-kf6-knewstuff-v6.10.0-patched.tar.gz
|
||||
d4783658caa5141b25aced8b5211c343bffb50a9425d50c8abc5193365976892 kde-kf6-knotifications-v6.10.0-patched.tar.gz
|
||||
3d84d8a9a3248ffc0d28d014912db2570ac582c0792a09585c1b1dc4319a1978 kde-kf6-kpackage-v6.10.0-patched.tar.gz
|
||||
7284d9158a17718239687ec032b21bee57cbd0ac6d446b9e5d35181bf2f28e1a kde-kf6-kservice-v6.10.0-patched.tar.gz
|
||||
06da94541e03d74c187788ff79e7669b4e2f743fb320b677891bef77c852f69a kde-kf6-ktextwidgets-v6.10.0-patched.tar.gz
|
||||
d837dd42e5c873860b8e8d1c6ca8a5147bc86bf4fc420cd2ea60e8e2c43209f1 kde-kf6-kwallet-v6.10.0-patched.tar.gz
|
||||
b2154c5c74f140816cbdafb19111b787ede155da3c78b6fbf52c7bc45cab1409 kde-kf6-kwayland-v6.3.4-patched.tar.gz
|
||||
b36ec1f1cd4959b2d8e4543a595a6a9de526143b5147ded18c78e3300ec3bd8a kde-kf6-kwidgetsaddons-v6.10.0-patched.tar.gz
|
||||
23e2bdab499dc5898df859dc0e3690b27f88b1e22db829798e8b6d60252267e2 kde-kf6-kwindowsystem-v6.10.0-patched.tar.gz
|
||||
7d73a7dd6a72c7f03644a4afa5ee2c57a3f4d04aad1725977ebb16325f39c47c kde-kf6-kxmlgui-v6.10.0-patched.tar.gz
|
||||
bd6ea6cc02c6e4020e80f307cd5d6adabd70b05d228bdb4f584a5ddc7284ffce kde-kf6-solid-v6.10.0-patched.tar.gz
|
||||
a577a8e3b70252156a8c622c71417e726606de37ed8a9c043d2e2359fc3b60b5 kde-kf6-sonnet-v6.10.0-patched.tar.gz
|
||||
95419c92002d893914fd31ffb48f71a0f34f07dc7bdce7427f0a0fd8493601ed kde-kglobalacceld-v6.0.0-patched.tar.gz
|
||||
4443841da66842d557cbdbbf7971d56554548ae98a44f023507542176e683117 kde-kirigami-v6.10.0-patched.tar.gz
|
||||
be98158da9f17efcc18c56f9cd132e68b300fcbb594ebe860a8b5357f18c8bd0 kde-kwin-v6.3.4-patched.tar.gz
|
||||
c1010706dfb8e00d349b24a2b3a525aedcc1d2e41227ee1673dd071cef8359ef kde-plasma-wayland-protocols-v1.16.0-patched.tar.gz
|
||||
1c8b0f5038240f01f1aac9f5cdf5f963ad355bca87118239aafa20b2a1b51fd2 libs-expat-v2.5.0-patched.tar.gz
|
||||
4953f6e273501761d0e6c2460b09b50922ebd53c2ad499c6aabce71c21708af9 libs-glib-v2.87-patched.tar.gz
|
||||
0e73529eac6877af802a680ea66291a7222327bdb313b7b44364cb2297d231c5 libs-lcms2-stub-vunknown-patched.tar.gz
|
||||
9b2f35c1fafb93de041105dd421b687fe05e7e6d6a8d1a5a5727c4992d6d39b5 libs-libdisplay-info-stub-vunknown-patched.tar.gz
|
||||
a0a37aaa219a1ab096ad294df04029a16b7bd2313b8002ebbdaf959fd6583225 libs-libepoxy-stub-vunknown-patched.tar.gz
|
||||
31828be1d165a7902487333e997cdab5d1b9429a12b5171d447afb92d424cbf7 libs-libevdev-vunknown-patched.tar.gz
|
||||
288d95219a2c0e4bd56fcdaea926ce9a04582bb80272dda4199a1c907c0f649b libs-libffi-v3.4.5-patched.tar.gz
|
||||
da3aca123e4668eabed1423698db6d4f39b27992743f72b89015ed962489b209 libs-libgcc-vunknown-patched.tar.gz
|
||||
d142df1affbc425a9e7542b4f8c9248f1149811c3b9da740ff3c33b3b3759b50 libs-libgmp-v6.3.0-patched.tar.gz
|
||||
bf9804f179eaf2548091931b91ae1fc5cd5a01b330dc85bc6bf097a9d2fbc0e9 libs-libiconv-v1.17-patched.tar.gz
|
||||
d9a76013904ac6497d4bef0305ac17efa1bdd1a3adebc1bfa437b6e3948ed358 libs-libinput-vunknown-patched.tar.gz
|
||||
09f63d7254e75360f0bae505336c750778313ed05ad69c50f6b6da208d197153 libs-liborbital.tar.gz
|
||||
f6714b4200ca33c9660009ec6487fbadf7afc56aa42537641ad75323d5a55af4 libs-liborbital-v9958363-patched.tar.gz
|
||||
cbfd9505dce77c42ce76d97d6d0a37abc50396ca95e8c214cbd26acbbc924c48 libs-libqrencode-vunknown-patched.tar.gz
|
||||
fd80625619d81631862572e466430d143e057f880f0299f20851e4e39f53265b libs-libstdcxx-v3-v8e365ce7e5-patched.tar.gz
|
||||
5d0312ddf758cc34ef7ee4428e1f7f6e3d9b7d8a64ec29cca888483a2daaa58b libs-libstdcxx-vunknown-patched.tar.gz
|
||||
f500f0bc22c3e586035f0a8d197f5f0b60dfcd3284f10f878470491eb6d54963 libs-libudev-stub-vunknown-patched.tar.gz
|
||||
f1e5de47ba6353b671a43938ccd430ce5f7d75063ee33e6eb2bf60bf8d302ff9 libs-libxcvt-stub-vunknown-patched.tar.gz
|
||||
efab18ac232c641efd116915cce08afe279e5c768f9447fedb44af349fdc809b libs-libxml2-v2.11-patched.tar.gz
|
||||
ad11eb07412afcd561fb8d1a5a33cc71cc98be4af498ebb3deedfca89ad99066 libs-linux-input-headers-v1.13.2-patched.tar.gz
|
||||
10733f31293e2b4edf2a48296dde7ec174b8273d86fc80294d38523554fa7132 libs-linux-input-headers-vunknown-patched.tar.gz
|
||||
6be00852e063056feb93adc2befba6738de148df910a953b5f0cd4ea1f2a4c1f libs-mesa.tar.gz
|
||||
7a6e727621e38ab1a376458a4693a0dabd02240f8c09eff8e94d7fb097866d30 libs-mesa-v0ecd6b66c-patched.tar.gz
|
||||
17b8f98b55298356745ba2533c374671ed5971786db64919641a1c2b9e698669 libs-mesa-va86b5f3ac-patched.tar.gz
|
||||
646c4e0b4100edd2dbcb43a7bea6f71e83bd15798be4a35af15a53d209a2149e libs-ncurses-v6.6-patched.tar.gz
|
||||
7b7d6bd13a85825c2b2154f2a1ce5833e97cbfdda75186e36574f89c3189039e libs-ncursesw-vunknown-patched.tar.gz
|
||||
8dd4168855f5022f5982aa0d556cf659e4cf0e778441d0469674f1c856f9b6aa libs-nghttp2-v1.64.0-patched.tar.gz
|
||||
27236afc509099c0ff9491a81d2afa982483ffd5a7f4b373a9c6c8719965a59c libs-pcre2-v10.45-patched.tar.gz
|
||||
d8fba8c19b69d3b0cb07473f0071ff077e8a0d411638b9a89858fe16e8e27217 libs-readline-v8.3-patched.tar.gz
|
||||
981bd0d9bfd57f38af1fde45b3cef7300ff67b133083092e7b3f7330c50e4e2c libs-termcap-v1.3.1-patched.tar.gz
|
||||
33e9d23d697c53245d54152ec9dbbe6d21543034003104d21dd8eb180936cf43 libs-zbus.tar.gz
|
||||
9130fffd118e2f0ad61cf0b98b26c1dcf0caee5aac456b04cd536c15e1abe3a1 libs-zbus-vunknown-patched.tar.gz
|
||||
93a7d8d5f25ff9f9a143d649161ebb857054bf133ca5a2246e66455dcd4f4c6e libs-zlib-v1.3-patched.tar.gz
|
||||
02b7f74d6149e3eea2e1e069f61595ae0943328cd5906f1dd84b407f26ab41d1 local-recipes-drivers-linux-kpi.tar.gz
|
||||
95899472009b85ba2b29fdc77e7ebdad926f81c86d071ca1c4f56b3e4617501c local-recipes-drivers-redox-driver-sys.tar.gz
|
||||
2c40bc71a01e4a35786644052999c2a1a5207d2100592cbd5e2002418409ec12 local-recipes-gpu-redox-drm.tar.gz
|
||||
413a49795400c91e2bb29eb6a7269567b4cd261fbc46bbaf466f91023d31108a monitors-bottom-v7cf3105d-patched.tar.gz
|
||||
e0a529cda4be63780a00f842194bf3e8293855c3533cc7802bee400712a8f1cd monitors-htop-vc9444cd3-patched.tar.gz
|
||||
841a848f29847679e9f2f1f70cbe7f2cd6b2a1ee3023872272dc77f24f1a11b4 other-ca-certificates-v8139d99-patched.tar.gz
|
||||
3ae5efcd34b7460b83173168b779d1a6c2a04554623d468fdf62cccd27b61d4c other-libevdev-v1.13.2-patched.tar.gz
|
||||
2fe33d35f4599d0ddf6972afeec393c4d761d9886e61f4af14a06225363b56b1 other-libinput-v1.30.2-patched.tar.gz
|
||||
26db541bf0c6f29b03e38f4c419f1e5aa933280e6ba666de63b64613bfcc316f other-libxkbcommon-v1.7.0-patched.tar.gz
|
||||
4295d94e0c4cf13d2563246928e4bd27a38dabef39cbb62cd9652ae3aac4f72a other-shared-mime-info-v2.4-patched.tar.gz
|
||||
9c93841855c95f98eb1be3972f0b63dbb62eef004577c19fd87e783f849075f9 other-terminfo-vdc5712b-patched.tar.gz
|
||||
33a00587669db9e3170ebc56d30cf9d24caa19b2b1a0d445c62eef535df900a8 qt-qt6-sensors-v6.11.0-patched.tar.gz
|
||||
6e569d30e590028b100bb6a8a19e9845a4f4d2054e83171b7ccd938c43700197 qt-qtbase-v6.11-patched.tar.gz
|
||||
1537c65840f5f739be7e111946981ce65cd22c256cdd1fa4b4db8919f661ea67 qt-qtdeclarative-v6.11-patched.tar.gz
|
||||
8c76cd8bd68377ba046e7c1ba9355ca9205706dadec963a90ba004cad729b453 qt-qtshadertools-v6.11-patched.tar.gz
|
||||
d92e719a14e7ab3f18ed8a6878c6ac6a5dd16e9b36afc470b18b0970204c4f9a qt-qtsvg-v6.11-patched.tar.gz
|
||||
5d59ddd50ebd5a6addcbad446405561db9583c129c1d2c7e203dbb8ffd5e47be qt-qtwayland-v6.11-patched.tar.gz
|
||||
369ad527a41701a8e99b5fe515c77b525812f5c8d2bce11d9961840ea7277b8d recipes-core-base.tar.gz
|
||||
1eec412c012d34a2fc24ba3e414e9e043ef0321c71138f7b2a0e7a136c834ef1 recipes-core-kernel.tar.gz
|
||||
93e05db4d8876d004be593fde5ce8e32da68f32b548aaa30a38db28c8357d57c recipes-core-relibc.tar.gz
|
||||
c2449ef6c4bb04b1fb11998b89bcbf53176637bac2d60c5c9d35e667eca47550 redbear-full-patches.tar.gz
|
||||
0836215d5f5a04b6fc846f8f98b4dd5dfd98c1f4ca7fbeca47b5cd01b2bc5c56 redbear-full-recipes.tar.gz
|
||||
6ee867a2defcd6a013ff2622913ba6de4425728ba2ba6b8544828d89563f4765 services-dbus-v1.16.2-patched.tar.gz
|
||||
2ce71338a83c0b17c257b3057d2c9988ff8bf958043d2a4d76d2fe60e383a815 services-seatd-v3f1eb28-patched.tar.gz
|
||||
8d576fd91b66cea8842f878a382c141261b390210e0e011390968b670359b272 shells-bash-v5.2.15-patched.tar.gz
|
||||
38628def4aad9fa4aef950da9e2de420973f9adf5d7cc606c5fa19ac799e8801 shells-zsh-v5.9-patched.tar.gz
|
||||
85a683e768c3d36d9234b2a7ad1a8c4e4c124c75921c1dafddd82d3c42351014 system-cub-vunknown-patched.tar.gz
|
||||
4916b35d619780fbf8a574c277a97c05d283b838743aa5eda8503b79452f1b06 system-evdevd-vunknown-patched.tar.gz
|
||||
9fc9633a945c4d365b0e1eb34f8d18a5c417ba11979ff79ba3687eb28b9fd5c1 system-firmware-loader-vunknown-patched.tar.gz
|
||||
d4cb8ed32b54271ffaf55019e27b8ecc065f0a2d40c93e40b64cab8e0dfc459b system-iommu-vunknown-patched.tar.gz
|
||||
694a9dbe3a8e78469078ca77868eb4e197041c19e70d3fec774ccd248b5f565a system-redbear-authd-vunknown-patched.tar.gz
|
||||
acaffb939037d7f47e59d529989fa1d07a730f8b110d0543359c890f43473e77 system-redbear-btctl-vunknown-patched.tar.gz
|
||||
933e4150fe644908ed14215ce65adfa7c4109045a439cf6d4b6915918886bb42 system-redbear-dbus-services-vunknown-patched.tar.gz
|
||||
2093c20a3c7469d8ccb745ddf89166f20b18897ebad93a51deb52e5b1754a565 system-redbear-firmware-vunknown-patched.tar.gz
|
||||
d800b22a152be6644b49b6e94a62aaa3d79fcae7b123f38b307e06a93abf63ff system-redbear-greeter-vunknown-patched.tar.gz
|
||||
d16af63308960d92ab53cc36ec42d8881f498e6df76f622887eb347a533fc4d4 system-redbear-hwutils-vunknown-patched.tar.gz
|
||||
5e9a0d4515ae3723ffa3d168587622b17aadc3dce3de6cb3517d6bb2ead8bc58 system-redbear-info-vunknown-patched.tar.gz
|
||||
6b373aa9efa9cc443546424ead7e059292b9fc18a7d30e61ee78bf45fce4eda8 system-redbear-login-protocol-vunknown-patched.tar.gz
|
||||
899d7f873581329c105a34d6ed250c7d480a846c7ec1d2517bf40f701650b6bf system-redbear-meta-vunknown-patched.tar.gz
|
||||
60d83c89ff4616dfb897aa1407cb4d50df9eea90fef0d0af4b0052208b87f7a8 system-redbear-mtr-vunknown-patched.tar.gz
|
||||
431d8f00a1e69abaab7efd569d901f143aa1ab025447ccc1ec4a54f9fb01eb52 system-redbear-netctl-console-vunknown-patched.tar.gz
|
||||
03be200f30feed1df7ffd4c398927227d3bedb5c98914a8b8182885f70955171 system-redbear-netctl-vunknown-patched.tar.gz
|
||||
02e497ed346e3be6ba2fb0696bbcfb3677405a7a7b3041686d74b9b3ea74e60e system-redbear-netstat-vunknown-patched.tar.gz
|
||||
4614f0094a0e3a4fbd9020bbf97af30614ae774c5bd5b6b768b73befe0ae52f4 system-redbear-nmap-vunknown-patched.tar.gz
|
||||
e28d97371b53a94e38d85d27dcacd0c20702df07a0f43a672dcea91026086197 system-redbear-notifications-vunknown-patched.tar.gz
|
||||
5a00ee80093d75b49fb261ee975337159de5678e805ce4f45e0172bbcd5154b2 system-redbear-passwd-vunknown-patched.tar.gz
|
||||
f278f8b45413a7dc0794e4e20d0e85c4f9ab10c053c87aa2ab64168b8ce9dccf system-redbear-polkit-vunknown-patched.tar.gz
|
||||
b73f27fa09f69b35119714156c0c1d51ed606a426ab1c075961433a13712c0ed system-redbear-quirks-vunknown-patched.tar.gz
|
||||
3212767ffb06b426fb6183e20efe240bc6625d6bc4570fdc52d4c145f8aefc75 system-redbear-sessiond-vunknown-patched.tar.gz
|
||||
6a56c56497e460a16011265f59ff79b3ec09f49268865aef194dfdb86baa4381 system-redbear-session-launch-vunknown-patched.tar.gz
|
||||
a945b57d5db1573bb372a9c990ee603688371e3dcfbcc6f8658e4899e63b31ab system-redbear-statusnotifierwatcher-vunknown-patched.tar.gz
|
||||
39a66dc9db654771752019e7880a537b64a197d50da4b3de218bfe8b97cc7679 system-redbear-traceroute-vunknown-patched.tar.gz
|
||||
d1554c1ac0a2bd1d8517d077748a8f6df202a3df19a5f641afe1048fb710e718 system-redbear-udisks-vunknown-patched.tar.gz
|
||||
78f7cba0fd6615e636f3de67cd5071116f7207d4295ba6053a3b03d3cef7c63b system-redbear-upower-vunknown-patched.tar.gz
|
||||
3a5df1ea45ae41391999c2368a5ddb68111bd6d507fd475077df26ab1162be21 system-redbear-wifictl-vunknown-patched.tar.gz
|
||||
7ebecf99b79e3c778ab754afc8cc37b19e7bafc7cc253f77ac300bb8f3c38453 system-udev-shim-vunknown-patched.tar.gz
|
||||
368eac6b32215479386cbc890fa3ed3664c8b2f93057d46c440533e9fa916860 tests-redox-drm-prime-test-vunknown-patched.tar.gz
|
||||
a6c6bdea2db16ea80746b0694fd0139f91b45d8884d3902eda3d12225a806366 tests-relibc-phase1-tests-vunknown-patched.tar.gz
|
||||
59d31683475d60881c265dcd90940117e8989af494d114865cbe2045f731e446 tests-relibc-tests-bins-v861bbb0-patched.tar.gz
|
||||
cd5cbb14c0fd791324b9a9092204e6506df3ef329384d4b673ae773e15d7bb3b tests-relibc-tests-v861bbb0-patched.tar.gz
|
||||
abacbb13c8cd322b6354195073955413aaf47f33b0068f574a7be856632b9d5f text-kibi-v274b371-patched.tar.gz
|
||||
872bbd46650c1d95bec31ae41583c93c10c57354cea98237ff7ac4ddd8e6ff4d tls-openssl3-v3.5.3-patched.tar.gz
|
||||
ed67149137d05652604a7b413b1e8e01d35f43220a28b79ca6e2b3ea2d51caa4 tools-bzip2-v1.0.8-patched.tar.gz
|
||||
e641a5081e426ebb6e040faa341317bb86fd517102517912edd34fbe300a5357 tools-diffutils-v3.6-patched.tar.gz
|
||||
a44c1070830b55046eadff1c00b2cda203aae2b5455def1c31b271437bfeab61 tools-gettext-v0.22.5-patched.tar.gz
|
||||
9142b86c6540364d521f4d6377f37d6fa3ee91f9b83287de321d1e35aa26a485 tools-patchelf-v0.18.0-patched.tar.gz
|
||||
baae7c04d9d3d19ec03eeb352f0958c4fd3f1194911803a88485d92b484b6a28 tools-xz-v5.2.13-patched.tar.gz
|
||||
cd580d47ad6392da89101229af43a875ce0d84378abf5a666dd65c83bdbb3d5f tui-mc-v4.8.33-patched.tar.gz
|
||||
9ca92b1564dcdbcaf7a9acb7489f4f8e8ab998d6f714139e9072d24cce4d354f wayland-libwayland-v1.24.0-patched.tar.gz
|
||||
e08c34a729eb71f93e194b801dcd219c958e9a3a999e3c90b18e901e748530ed wayland-qt6-wayland-smoke-vunknown-patched.tar.gz
|
||||
3fe4ebda86ca28acaede4f1379fba0eceb18a65e3cbc6cd6a372e741cc317149 wayland-redbear-compositor-vunknown-patched.tar.gz
|
||||
a517ec643eb7b373b7bf9748e353c688a7ea0f7ef070f66e92b9d8f879fbfa25 wayland-wayland-protocols-v1.38-patched.tar.gz
|
||||
09ed779f68238b71d1b68d9d8c6248e2e6598cb28b0c20f0348b723f3b6d5577 x11-libdrm-v2.4.125-patched.tar.gz
|
||||
c455fe44cde03931c96f8c183776e83b34f4e08a0e64fdd87aa3f74b8c846729 x11-mesa-x11-va86b5f3ac-patched.tar.gz
|
||||
@@ -0,0 +1 @@
|
||||
PODMAN_BUILD?=0
|
||||
@@ -0,0 +1,320 @@
|
||||
# Base configuration: This configuration is meant to be included by
|
||||
# other configurations rather than use directly. It is the greatest
|
||||
# common divisor of all other configurations and misses several
|
||||
# parts necessary to create a bootable system.
|
||||
|
||||
# General settings
|
||||
[general]
|
||||
# Do not prompt if settings are not defined
|
||||
prompt = false
|
||||
|
||||
[packages]
|
||||
base = {}
|
||||
base-initfs = {}
|
||||
bootloader = {}
|
||||
kernel = {}
|
||||
libgcc = {}
|
||||
libstdcxx = {}
|
||||
netdb = {}
|
||||
netutils = {}
|
||||
relibc = {}
|
||||
userutils = {}
|
||||
uutils = {}
|
||||
|
||||
## Configuration files
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/00_base.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Base environment setup (tmpdir)"
|
||||
|
||||
[service]
|
||||
cmd = "ion"
|
||||
args = ["-c", "rm -rf /tmp; mkdir -m a=rwxt /tmp"]
|
||||
type = "oneshot"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/00_sudo.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Sudo privilege daemon"
|
||||
|
||||
[service]
|
||||
cmd = "sudo"
|
||||
args = ["--daemon"]
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/login_schemes.toml"
|
||||
data = """
|
||||
[user_schemes.root]
|
||||
schemes = ["*"]
|
||||
[user_schemes.user]
|
||||
schemes = [
|
||||
# Kernel schemes
|
||||
"debug",
|
||||
"event",
|
||||
"memory",
|
||||
"pipe",
|
||||
"serio",
|
||||
"irq",
|
||||
"time",
|
||||
"sys",
|
||||
# Base schemes
|
||||
"rand",
|
||||
"null",
|
||||
"zero",
|
||||
"log",
|
||||
# Network schemes
|
||||
"ip",
|
||||
"icmp",
|
||||
"tcp",
|
||||
"udp",
|
||||
# IPC schemes
|
||||
"shm",
|
||||
"chan",
|
||||
"uds_stream",
|
||||
"uds_dgram",
|
||||
# File schemes
|
||||
"file",
|
||||
# Display schemes
|
||||
"display.vesa",
|
||||
"display*",
|
||||
# Other schemes
|
||||
"pty",
|
||||
"sudo",
|
||||
"audio",
|
||||
]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/hostname"
|
||||
data = "redbear"
|
||||
|
||||
## Default net configuration (optimized for QEMU)
|
||||
[[files]]
|
||||
path = "/etc/net/dns"
|
||||
data = """
|
||||
9.9.9.9
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/net/ip"
|
||||
data = """
|
||||
10.0.2.15
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/net/ip_router"
|
||||
data = """
|
||||
10.0.2.2
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/net/ip_subnet"
|
||||
data = """
|
||||
255.255.255.0
|
||||
"""
|
||||
|
||||
# https://www.freedesktop.org/software/systemd/man/latest/os-release.html
|
||||
[[files]]
|
||||
path = "/usr/lib/os-release"
|
||||
data = """
|
||||
PRETTY_NAME="Red Bear OS 0.1.0"
|
||||
NAME="Red Bear OS"
|
||||
VERSION_ID="0.1.0"
|
||||
VERSION="0.1.0"
|
||||
ID="redbear-os"
|
||||
ID_LIKE="redox-os"
|
||||
|
||||
HOME_URL="https://github.com/vasilito/Red-Bear-OS-3"
|
||||
DOCUMENTATION_URL="https://doc.redox-os.org/"
|
||||
SUPPORT_URL="https://github.com/vasilito/Red-Bear-OS-3/issues"
|
||||
"""
|
||||
# FIXME maybe add VARIANT= and VARIANT_ID= keys depending on the chosen configuration?
|
||||
|
||||
[[files]]
|
||||
path = "/etc/os-release"
|
||||
data = "../usr/lib/os-release"
|
||||
symlink = true
|
||||
|
||||
[[files]]
|
||||
path = "/etc/pkg.d/50_redox"
|
||||
data = "https://static.redox-os.org/pkg"
|
||||
|
||||
## /usr and symlinks for usrmerge
|
||||
[[files]]
|
||||
path = "/usr"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o755
|
||||
|
||||
[[files]]
|
||||
path = "/usr/bin"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o755
|
||||
|
||||
[[files]]
|
||||
path = "/bin"
|
||||
data = "usr/bin"
|
||||
symlink = true
|
||||
|
||||
[[files]]
|
||||
path = "/usr/include"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o755
|
||||
|
||||
[[files]]
|
||||
path = "/include"
|
||||
data = "usr/include"
|
||||
symlink = true
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o755
|
||||
|
||||
[[files]]
|
||||
path = "/lib"
|
||||
data = "usr/lib"
|
||||
symlink = true
|
||||
|
||||
[[files]]
|
||||
path = "/usr/libexec"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o755
|
||||
|
||||
[[files]]
|
||||
path = "/usr/share"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o755
|
||||
|
||||
[[files]]
|
||||
path = "/share"
|
||||
data = "usr/share"
|
||||
symlink = true
|
||||
|
||||
[[files]]
|
||||
path = "/ui"
|
||||
data = "usr/share/ui"
|
||||
symlink = true
|
||||
|
||||
## legacy display font directory
|
||||
[[files]]
|
||||
path = "/usr/share/ui/fonts"
|
||||
data = "/usr/share/fonts"
|
||||
symlink = true
|
||||
|
||||
## legacy display icon directory
|
||||
[[files]]
|
||||
path = "/usr/share/ui/icons"
|
||||
data = "/usr/share/icons"
|
||||
symlink = true
|
||||
|
||||
## /var
|
||||
[[files]]
|
||||
path = "/var"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o755
|
||||
|
||||
[[files]]
|
||||
path = "/var/cache"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o755
|
||||
|
||||
[[files]]
|
||||
path = "/var/lib"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o755
|
||||
|
||||
[[files]]
|
||||
path = "/var/lock"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o1777
|
||||
|
||||
[[files]]
|
||||
path = "/var/log"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o755
|
||||
|
||||
[[files]]
|
||||
path = "/var/run"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o755
|
||||
|
||||
[[files]]
|
||||
path = "/var/tmp"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o1777
|
||||
|
||||
## Device file symlinks
|
||||
[[files]]
|
||||
path = "/dev/null"
|
||||
data = "/scheme/null"
|
||||
symlink = true
|
||||
|
||||
[[files]]
|
||||
path = "/dev/random"
|
||||
data = "/scheme/rand"
|
||||
symlink = true
|
||||
|
||||
[[files]]
|
||||
path = "/dev/urandom"
|
||||
data = "/scheme/rand"
|
||||
symlink = true
|
||||
|
||||
[[files]]
|
||||
path = "/dev/zero"
|
||||
data = "/scheme/zero"
|
||||
symlink = true
|
||||
|
||||
[[files]]
|
||||
path = "/dev/tty"
|
||||
data = "libc:tty"
|
||||
symlink = true
|
||||
|
||||
[[files]]
|
||||
path = "/dev/stdin"
|
||||
data = "libc:stdin"
|
||||
symlink = true
|
||||
|
||||
[[files]]
|
||||
path = "/dev/stdout"
|
||||
data = "libc:stdout"
|
||||
symlink = true
|
||||
|
||||
[[files]]
|
||||
path = "/dev/stderr"
|
||||
data = "libc:stderr"
|
||||
symlink = true
|
||||
|
||||
# User settings
|
||||
[users.root]
|
||||
password = "password"
|
||||
uid = 0
|
||||
gid = 0
|
||||
shell = "/usr/bin/ion"
|
||||
|
||||
[users.user]
|
||||
# Password is unset
|
||||
password = ""
|
||||
shell = "/usr/bin/ion"
|
||||
|
||||
# Group settings
|
||||
[groups.sudo]
|
||||
gid = 1
|
||||
members = ["user"]
|
||||
@@ -0,0 +1,56 @@
|
||||
# Minimal configuration
|
||||
|
||||
include = ["base.toml"]
|
||||
|
||||
# General settings
|
||||
[general]
|
||||
# Filesystem size in MiB
|
||||
filesystem_size = 196
|
||||
|
||||
# Package settings
|
||||
[packages]
|
||||
ca-certificates = {}
|
||||
coreutils = {}
|
||||
extrautils = {}
|
||||
ion = {}
|
||||
pkgutils = {}
|
||||
kibi = {}
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/29_activate_console.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Activate console VT"
|
||||
requires_weak = ["00_base.target"]
|
||||
|
||||
[service]
|
||||
cmd = "inputd"
|
||||
args = ["-A", "2"]
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/30_console.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Console terminals"
|
||||
requires_weak = ["29_activate_console.service"]
|
||||
|
||||
[service]
|
||||
cmd = "getty"
|
||||
args = ["2"]
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/31_debug_console.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Debug console"
|
||||
requires_weak = ["29_activate_console.service"]
|
||||
|
||||
[service]
|
||||
cmd = "getty"
|
||||
args = ["/scheme/debug/no-preserve", "-J"]
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
@@ -0,0 +1,17 @@
|
||||
# Red Bear OS Bluetooth Experimental Profile
|
||||
#
|
||||
# Standalone build target for the first bounded Bluetooth slice.
|
||||
#
|
||||
# This profile extends the existing minimal Red Bear baseline but keeps Bluetooth wiring isolated to
|
||||
# this profile instead of leaking it into the shared device-service fragments used by all images.
|
||||
# The current slice is explicit-startup, USB-attached, BLE-first, and intentionally not wired to
|
||||
# USB-class autospawn yet.
|
||||
|
||||
include = ["redbear-minimal.toml", "redbear-bluetooth-services.toml"]
|
||||
|
||||
[general]
|
||||
filesystem_size = 2048
|
||||
|
||||
[packages]
|
||||
redbear-btusb = {}
|
||||
redbear-btctl = {}
|
||||
@@ -0,0 +1,17 @@
|
||||
# Red Bear OS Bluetooth experimental service wiring
|
||||
#
|
||||
# Kept in a dedicated included fragment so the Bluetooth profile can inject
|
||||
# bounded runtime files and service units without relying on profile-local
|
||||
# [[files]] behavior.
|
||||
|
||||
[[files]]
|
||||
path = "/var/lib/bluetooth"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o755
|
||||
|
||||
[[files]]
|
||||
path = "/var/run/redbear-btusb"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o755
|
||||
@@ -0,0 +1,829 @@
|
||||
# Red Bear OS shared device-service wiring
|
||||
#
|
||||
# Shared by profiles that ship the firmware/input/Wi-Fi control compatibility stack.
|
||||
|
||||
[packages]
|
||||
redbear-quirks = {}
|
||||
pciids = {}
|
||||
fatd = {}
|
||||
|
||||
# Firmware fallback chain configs
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/00-amdgpu.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn31.bin"
|
||||
chain = ["amdgpu/dmcub_dcn30.bin", "amdgpu/dmcub_dcn20.bin"]
|
||||
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn30.bin"
|
||||
chain = ["amdgpu/dmcub_dcn20.bin"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/10-iwlwifi.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "iwlwifi-bz-b0-gf-a0-92.ucode"
|
||||
chain = ["iwlwifi-bz-b0-gf-a0-83.ucode", "iwlwifi-bz-b0-gf-a0-77.ucode"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/20-intel-dmc.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "i915/adlp_dmc_ver2_16.bin"
|
||||
chain = ["i915/adlp_dmc_ver2_14.bin", "i915/adlp_dmc_ver2_12.bin"]
|
||||
"""
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/12_boot-late.target"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Late boot services target"
|
||||
requires_weak = [
|
||||
"00_base.target",
|
||||
]
|
||||
"""
|
||||
|
||||
# Firmware fallback chain configs
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/00-amdgpu.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn31.bin"
|
||||
chain = ["amdgpu/dmcub_dcn30.bin", "amdgpu/dmcub_dcn20.bin"]
|
||||
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn30.bin"
|
||||
chain = ["amdgpu/dmcub_dcn20.bin"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/10-iwlwifi.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "iwlwifi-bz-b0-gf-a0-92.ucode"
|
||||
chain = ["iwlwifi-bz-b0-gf-a0-83.ucode", "iwlwifi-bz-b0-gf-a0-77.ucode"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/20-intel-dmc.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "i915/adlp_dmc_ver2_16.bin"
|
||||
chain = ["i915/adlp_dmc_ver2_14.bin", "i915/adlp_dmc_ver2_12.bin"]
|
||||
"""
|
||||
[[files]]
|
||||
path = "/lib/drivers.d"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o755
|
||||
|
||||
# Firmware fallback chain configs
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/00-amdgpu.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn31.bin"
|
||||
chain = ["amdgpu/dmcub_dcn30.bin", "amdgpu/dmcub_dcn20.bin"]
|
||||
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn30.bin"
|
||||
chain = ["amdgpu/dmcub_dcn20.bin"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/10-iwlwifi.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "iwlwifi-bz-b0-gf-a0-92.ucode"
|
||||
chain = ["iwlwifi-bz-b0-gf-a0-83.ucode", "iwlwifi-bz-b0-gf-a0-77.ucode"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/20-intel-dmc.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "i915/adlp_dmc_ver2_16.bin"
|
||||
chain = ["i915/adlp_dmc_ver2_14.bin", "i915/adlp_dmc_ver2_12.bin"]
|
||||
"""
|
||||
[[files]]
|
||||
path = "/lib/drivers.d/00-storage.toml"
|
||||
data = """
|
||||
[[driver]]
|
||||
name = "nvmed"
|
||||
description = "NVMe storage driver"
|
||||
priority = 100
|
||||
command = ["/usr/lib/drivers/nvmed"]
|
||||
|
||||
[[driver.match]]
|
||||
class = 1
|
||||
subclass = 8
|
||||
|
||||
[[driver]]
|
||||
name = "ahcid"
|
||||
description = "AHCI SATA driver"
|
||||
priority = 100
|
||||
command = ["/usr/lib/drivers/ahcid"]
|
||||
|
||||
[[driver.match]]
|
||||
class = 1
|
||||
subclass = 6
|
||||
|
||||
[[driver]]
|
||||
name = "ided"
|
||||
description = "PATA IDE driver"
|
||||
priority = 100
|
||||
command = ["/usr/lib/drivers/ided"]
|
||||
|
||||
[[driver.match]]
|
||||
class = 1
|
||||
subclass = 1
|
||||
|
||||
[[driver]]
|
||||
name = "virtio-blkd"
|
||||
description = "VirtIO block device driver"
|
||||
priority = 100
|
||||
command = ["/usr/lib/drivers/virtio-blkd"]
|
||||
|
||||
[[driver.match]]
|
||||
vendor = 0x1AF4
|
||||
device = 0x1001
|
||||
class = 1
|
||||
subclass = 0
|
||||
"""
|
||||
|
||||
# Firmware fallback chain configs
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/00-amdgpu.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn31.bin"
|
||||
chain = ["amdgpu/dmcub_dcn30.bin", "amdgpu/dmcub_dcn20.bin"]
|
||||
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn30.bin"
|
||||
chain = ["amdgpu/dmcub_dcn20.bin"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/10-iwlwifi.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "iwlwifi-bz-b0-gf-a0-92.ucode"
|
||||
chain = ["iwlwifi-bz-b0-gf-a0-83.ucode", "iwlwifi-bz-b0-gf-a0-77.ucode"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/20-intel-dmc.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "i915/adlp_dmc_ver2_16.bin"
|
||||
chain = ["i915/adlp_dmc_ver2_14.bin", "i915/adlp_dmc_ver2_12.bin"]
|
||||
"""
|
||||
[[files]]
|
||||
path = "/lib/drivers.d/10-network.toml"
|
||||
data = """
|
||||
[[driver]]
|
||||
name = "e1000d"
|
||||
description = "Intel Gigabit Ethernet"
|
||||
priority = 50
|
||||
command = ["/usr/lib/drivers/e1000d"]
|
||||
|
||||
[[driver.match]]
|
||||
vendor = 0x8086
|
||||
class = 2
|
||||
|
||||
[[driver]]
|
||||
name = "rtl8168d"
|
||||
description = "Realtek 8168/8125 Ethernet"
|
||||
priority = 50
|
||||
command = ["/usr/lib/drivers/rtl8168d"]
|
||||
|
||||
[[driver.match]]
|
||||
vendor = 0x10EC
|
||||
class = 2
|
||||
|
||||
[[driver]]
|
||||
name = "rtl8139d"
|
||||
description = "Realtek 8139 Ethernet"
|
||||
priority = 50
|
||||
command = ["/usr/lib/drivers/rtl8139d"]
|
||||
|
||||
[[driver.match]]
|
||||
vendor = 0x10EC
|
||||
device = 0x8139
|
||||
|
||||
[[driver]]
|
||||
name = "ixgbed"
|
||||
description = "Intel 10 Gigabit Ethernet"
|
||||
priority = 50
|
||||
command = ["/usr/lib/drivers/ixgbed"]
|
||||
|
||||
[[driver.match]]
|
||||
vendor = 0x8086
|
||||
class = 2
|
||||
subclass = 0
|
||||
|
||||
[[driver]]
|
||||
name = "virtio-netd"
|
||||
description = "VirtIO network driver"
|
||||
priority = 50
|
||||
command = ["/usr/lib/drivers/virtio-netd"]
|
||||
|
||||
[[driver.match]]
|
||||
vendor = 0x1AF4
|
||||
class = 2
|
||||
"""
|
||||
|
||||
# Firmware fallback chain configs
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/00-amdgpu.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn31.bin"
|
||||
chain = ["amdgpu/dmcub_dcn30.bin", "amdgpu/dmcub_dcn20.bin"]
|
||||
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn30.bin"
|
||||
chain = ["amdgpu/dmcub_dcn20.bin"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/10-iwlwifi.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "iwlwifi-bz-b0-gf-a0-92.ucode"
|
||||
chain = ["iwlwifi-bz-b0-gf-a0-83.ucode", "iwlwifi-bz-b0-gf-a0-77.ucode"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/20-intel-dmc.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "i915/adlp_dmc_ver2_16.bin"
|
||||
chain = ["i915/adlp_dmc_ver2_14.bin", "i915/adlp_dmc_ver2_12.bin"]
|
||||
"""
|
||||
[[files]]
|
||||
path = "/lib/drivers.d/20-usb.toml"
|
||||
data = """
|
||||
[[driver]]
|
||||
name = "xhcid"
|
||||
description = "xHCI USB host controller"
|
||||
priority = 80
|
||||
command = ["/usr/lib/drivers/xhcid"]
|
||||
|
||||
[[driver.match]]
|
||||
class = 0x0C
|
||||
subclass = 0x03
|
||||
prog_if = 0x30
|
||||
|
||||
[[driver]]
|
||||
name = "ehcid"
|
||||
description = "EHCI USB 2.0 host controller"
|
||||
priority = 80
|
||||
command = ["/usr/lib/drivers/ehcid"]
|
||||
|
||||
# EHCI now owns a simple /scheme/usb controller surface for per-port status and
|
||||
# control-transfer pass-through while the wider USB stack continues converging.
|
||||
|
||||
[[driver.match]]
|
||||
class = 0x0C
|
||||
subclass = 0x03
|
||||
prog_if = 0x20
|
||||
|
||||
[[driver]]
|
||||
name = "ohcid"
|
||||
description = "OHCI USB 1.1 host controller"
|
||||
priority = 80
|
||||
command = ["/usr/lib/drivers/ohcid"]
|
||||
|
||||
[[driver.match]]
|
||||
class = 0x0C
|
||||
subclass = 0x03
|
||||
prog_if = 0x10
|
||||
|
||||
[[driver]]
|
||||
name = "uhcid"
|
||||
description = "UHCI USB 1.1 host controller (Intel)"
|
||||
priority = 80
|
||||
command = ["/usr/lib/drivers/uhcid"]
|
||||
|
||||
[[driver.match]]
|
||||
class = 0x0C
|
||||
subclass = 0x03
|
||||
prog_if = 0x00
|
||||
"""
|
||||
|
||||
# Firmware fallback chain configs
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/00-amdgpu.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn31.bin"
|
||||
chain = ["amdgpu/dmcub_dcn30.bin", "amdgpu/dmcub_dcn20.bin"]
|
||||
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn30.bin"
|
||||
chain = ["amdgpu/dmcub_dcn20.bin"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/10-iwlwifi.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "iwlwifi-bz-b0-gf-a0-92.ucode"
|
||||
chain = ["iwlwifi-bz-b0-gf-a0-83.ucode", "iwlwifi-bz-b0-gf-a0-77.ucode"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/20-intel-dmc.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "i915/adlp_dmc_ver2_16.bin"
|
||||
chain = ["i915/adlp_dmc_ver2_14.bin", "i915/adlp_dmc_ver2_12.bin"]
|
||||
"""
|
||||
[[files]]
|
||||
path = "/lib/drivers.d/30-graphics.toml"
|
||||
data = """
|
||||
[[driver]]
|
||||
name = "vesad"
|
||||
description = "VESA BIOS display driver"
|
||||
priority = 60
|
||||
command = ["/usr/lib/drivers/vesad"]
|
||||
|
||||
[[driver.match]]
|
||||
class = 0x03
|
||||
|
||||
[[driver]]
|
||||
name = "redox-drm"
|
||||
description = "DRM/KMS display driver (AMD + Intel)"
|
||||
priority = 60
|
||||
command = ["/usr/bin/redox-drm"]
|
||||
|
||||
[[driver.match]]
|
||||
class = 0x03
|
||||
"""
|
||||
|
||||
# Firmware fallback chain configs
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/00-amdgpu.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn31.bin"
|
||||
chain = ["amdgpu/dmcub_dcn30.bin", "amdgpu/dmcub_dcn20.bin"]
|
||||
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn30.bin"
|
||||
chain = ["amdgpu/dmcub_dcn20.bin"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/10-iwlwifi.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "iwlwifi-bz-b0-gf-a0-92.ucode"
|
||||
chain = ["iwlwifi-bz-b0-gf-a0-83.ucode", "iwlwifi-bz-b0-gf-a0-77.ucode"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/20-intel-dmc.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "i915/adlp_dmc_ver2_16.bin"
|
||||
chain = ["i915/adlp_dmc_ver2_14.bin", "i915/adlp_dmc_ver2_12.bin"]
|
||||
"""
|
||||
[[files]]
|
||||
path = "/lib/drivers.d/40-input.toml"
|
||||
data = """
|
||||
[[driver]]
|
||||
name = "ps2d"
|
||||
description = "PS/2 keyboard and mouse driver"
|
||||
priority = 90
|
||||
command = ["/usr/lib/drivers/ps2d"]
|
||||
"""
|
||||
|
||||
# Firmware fallback chain configs
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/00-amdgpu.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn31.bin"
|
||||
chain = ["amdgpu/dmcub_dcn30.bin", "amdgpu/dmcub_dcn20.bin"]
|
||||
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn30.bin"
|
||||
chain = ["amdgpu/dmcub_dcn20.bin"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/10-iwlwifi.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "iwlwifi-bz-b0-gf-a0-92.ucode"
|
||||
chain = ["iwlwifi-bz-b0-gf-a0-83.ucode", "iwlwifi-bz-b0-gf-a0-77.ucode"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/20-intel-dmc.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "i915/adlp_dmc_ver2_16.bin"
|
||||
chain = ["i915/adlp_dmc_ver2_14.bin", "i915/adlp_dmc_ver2_12.bin"]
|
||||
"""
|
||||
[[files]]
|
||||
path = "/lib/drivers.d/50-audio.toml"
|
||||
data = """
|
||||
[[driver]]
|
||||
name = "ihdad"
|
||||
description = "Intel HD Audio driver"
|
||||
priority = 40
|
||||
command = ["/usr/lib/drivers/ihdad"]
|
||||
|
||||
[[driver.match]]
|
||||
vendor = 0x8086
|
||||
class = 0x04
|
||||
|
||||
[[driver]]
|
||||
name = "ac97d"
|
||||
description = "AC'97 audio codec driver"
|
||||
priority = 40
|
||||
command = ["/usr/lib/drivers/ac97d"]
|
||||
|
||||
[[driver.match]]
|
||||
class = 0x04
|
||||
subclass = 0x01
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/lib/drivers.d/70-usb-class.toml"
|
||||
data = """
|
||||
[[driver]]
|
||||
name = "redbear-acmd"
|
||||
description = "USB CDC ACM serial driver"
|
||||
priority = 70
|
||||
command = ["/usr/bin/redbear-acmd"]
|
||||
|
||||
[[driver]]
|
||||
name = "redbear-ecmd"
|
||||
description = "USB CDC ECM/NCM ethernet driver"
|
||||
priority = 70
|
||||
command = ["/usr/bin/redbear-ecmd"]
|
||||
|
||||
[[driver]]
|
||||
name = "redbear-usbaudiod"
|
||||
description = "USB Audio Class driver"
|
||||
priority = 70
|
||||
command = ["/usr/bin/redbear-usbaudiod"]
|
||||
"""
|
||||
|
||||
# Profiles that include this fragment should start `driver-manager` instead of
|
||||
# `pcid-spawner`; the manager performs the PCI bind/channel handoff itself.
|
||||
# Firmware fallback chain configs
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/00-amdgpu.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn31.bin"
|
||||
chain = ["amdgpu/dmcub_dcn30.bin", "amdgpu/dmcub_dcn20.bin"]
|
||||
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn30.bin"
|
||||
chain = ["amdgpu/dmcub_dcn20.bin"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/10-iwlwifi.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "iwlwifi-bz-b0-gf-a0-92.ucode"
|
||||
chain = ["iwlwifi-bz-b0-gf-a0-83.ucode", "iwlwifi-bz-b0-gf-a0-77.ucode"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/20-intel-dmc.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "i915/adlp_dmc_ver2_16.bin"
|
||||
chain = ["i915/adlp_dmc_ver2_14.bin", "i915/adlp_dmc_ver2_12.bin"]
|
||||
"""
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/00_driver-manager.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "PCI driver spawner"
|
||||
requires_weak = [
|
||||
"00_base.target",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "pcid-spawner"
|
||||
type = "oneshot"
|
||||
"""
|
||||
|
||||
# Firmware fallback chain configs
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/00-amdgpu.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn31.bin"
|
||||
chain = ["amdgpu/dmcub_dcn30.bin", "amdgpu/dmcub_dcn20.bin"]
|
||||
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn30.bin"
|
||||
chain = ["amdgpu/dmcub_dcn20.bin"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/10-iwlwifi.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "iwlwifi-bz-b0-gf-a0-92.ucode"
|
||||
chain = ["iwlwifi-bz-b0-gf-a0-83.ucode", "iwlwifi-bz-b0-gf-a0-77.ucode"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/20-intel-dmc.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "i915/adlp_dmc_ver2_16.bin"
|
||||
chain = ["i915/adlp_dmc_ver2_14.bin", "i915/adlp_dmc_ver2_12.bin"]
|
||||
"""
|
||||
[[files]]
|
||||
path = "/lib/drivers.d"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o755
|
||||
|
||||
# Firmware fallback chain configs
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/00-amdgpu.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn31.bin"
|
||||
chain = ["amdgpu/dmcub_dcn30.bin", "amdgpu/dmcub_dcn20.bin"]
|
||||
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn30.bin"
|
||||
chain = ["amdgpu/dmcub_dcn20.bin"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/10-iwlwifi.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "iwlwifi-bz-b0-gf-a0-92.ucode"
|
||||
chain = ["iwlwifi-bz-b0-gf-a0-83.ucode", "iwlwifi-bz-b0-gf-a0-77.ucode"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/20-intel-dmc.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "i915/adlp_dmc_ver2_16.bin"
|
||||
chain = ["i915/adlp_dmc_ver2_14.bin", "i915/adlp_dmc_ver2_12.bin"]
|
||||
"""
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/10_evdevd.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Evdev input daemon"
|
||||
requires_weak = [
|
||||
"12_boot-late.target",
|
||||
"00_pcid-spawner.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "evdevd"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
# Firmware fallback chain configs
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/00-amdgpu.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn31.bin"
|
||||
chain = ["amdgpu/dmcub_dcn30.bin", "amdgpu/dmcub_dcn20.bin"]
|
||||
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn30.bin"
|
||||
chain = ["amdgpu/dmcub_dcn20.bin"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/10-iwlwifi.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "iwlwifi-bz-b0-gf-a0-92.ucode"
|
||||
chain = ["iwlwifi-bz-b0-gf-a0-83.ucode", "iwlwifi-bz-b0-gf-a0-77.ucode"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/20-intel-dmc.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "i915/adlp_dmc_ver2_16.bin"
|
||||
chain = ["i915/adlp_dmc_ver2_14.bin", "i915/adlp_dmc_ver2_12.bin"]
|
||||
"""
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o755
|
||||
|
||||
# Firmware fallback chain configs
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/00-amdgpu.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn31.bin"
|
||||
chain = ["amdgpu/dmcub_dcn30.bin", "amdgpu/dmcub_dcn20.bin"]
|
||||
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn30.bin"
|
||||
chain = ["amdgpu/dmcub_dcn20.bin"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/10-iwlwifi.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "iwlwifi-bz-b0-gf-a0-92.ucode"
|
||||
chain = ["iwlwifi-bz-b0-gf-a0-83.ucode", "iwlwifi-bz-b0-gf-a0-77.ucode"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/20-intel-dmc.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "i915/adlp_dmc_ver2_16.bin"
|
||||
chain = ["i915/adlp_dmc_ver2_14.bin", "i915/adlp_dmc_ver2_12.bin"]
|
||||
"""
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/15_cpufreqd.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "CPU frequency scaling daemon"
|
||||
requires_weak = ["12_boot-late.target"]
|
||||
|
||||
[service]
|
||||
cmd = "/usr/bin/cpufreqd"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
# Firmware fallback chain configs
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/00-amdgpu.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn31.bin"
|
||||
chain = ["amdgpu/dmcub_dcn30.bin", "amdgpu/dmcub_dcn20.bin"]
|
||||
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn30.bin"
|
||||
chain = ["amdgpu/dmcub_dcn20.bin"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/10-iwlwifi.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "iwlwifi-bz-b0-gf-a0-92.ucode"
|
||||
chain = ["iwlwifi-bz-b0-gf-a0-83.ucode", "iwlwifi-bz-b0-gf-a0-77.ucode"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/20-intel-dmc.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "i915/adlp_dmc_ver2_16.bin"
|
||||
chain = ["i915/adlp_dmc_ver2_14.bin", "i915/adlp_dmc_ver2_12.bin"]
|
||||
"""
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/15_thermald.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Thermal management daemon"
|
||||
requires_weak = ["12_boot-late.target"]
|
||||
|
||||
[service]
|
||||
cmd = "/usr/bin/thermald"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
# Firmware fallback chain configs
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/00-amdgpu.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn31.bin"
|
||||
chain = ["amdgpu/dmcub_dcn30.bin", "amdgpu/dmcub_dcn20.bin"]
|
||||
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn30.bin"
|
||||
chain = ["amdgpu/dmcub_dcn20.bin"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/10-iwlwifi.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "iwlwifi-bz-b0-gf-a0-92.ucode"
|
||||
chain = ["iwlwifi-bz-b0-gf-a0-83.ucode", "iwlwifi-bz-b0-gf-a0-77.ucode"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/20-intel-dmc.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "i915/adlp_dmc_ver2_16.bin"
|
||||
chain = ["i915/adlp_dmc_ver2_14.bin", "i915/adlp_dmc_ver2_12.bin"]
|
||||
"""
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/15_hwrngd.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Hardware RNG entropy daemon"
|
||||
requires_weak = ["00_base.target"]
|
||||
|
||||
[service]
|
||||
cmd = "/usr/bin/hwrngd"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
# Firmware fallback chain configs
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/00-amdgpu.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn31.bin"
|
||||
chain = ["amdgpu/dmcub_dcn30.bin", "amdgpu/dmcub_dcn20.bin"]
|
||||
|
||||
[[fallback]]
|
||||
pattern = "amdgpu/dmcub_dcn30.bin"
|
||||
chain = ["amdgpu/dmcub_dcn20.bin"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/10-iwlwifi.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "iwlwifi-bz-b0-gf-a0-92.ucode"
|
||||
chain = ["iwlwifi-bz-b0-gf-a0-83.ucode", "iwlwifi-bz-b0-gf-a0-77.ucode"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/firmware-fallbacks.d/20-intel-dmc.toml"
|
||||
data = """
|
||||
[[fallback]]
|
||||
pattern = "i915/adlp_dmc_ver2_16.bin"
|
||||
chain = ["i915/adlp_dmc_ver2_14.bin", "i915/adlp_dmc_ver2_12.bin"]
|
||||
"""
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/13_driver-params.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Driver parameter scheme"
|
||||
requires_weak = ["00_driver-manager.service"]
|
||||
|
||||
[service]
|
||||
cmd = "/usr/bin/driver-params"
|
||||
type = { scheme = "driver-params" }
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/16_redbear-acmd.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "USB CDC ACM serial daemon"
|
||||
requires_weak = ["12_boot-late.target"]
|
||||
|
||||
[service]
|
||||
cmd = "/usr/bin/redbear-acmd"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/16_redbear-ecmd.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "USB CDC ECM/NCM ethernet daemon"
|
||||
requires_weak = ["12_boot-late.target"]
|
||||
|
||||
[service]
|
||||
cmd = "/usr/bin/redbear-ecmd"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/16_redbear-usbaudiod.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "USB Audio Class daemon"
|
||||
requires_weak = ["12_boot-late.target"]
|
||||
|
||||
[service]
|
||||
cmd = "/usr/bin/redbear-usbaudiod"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
@@ -0,0 +1,408 @@
|
||||
# Red Bear OS Full Configuration
|
||||
# Desktop/graphics ISO for bare metal and QEMU.
|
||||
#
|
||||
# Build: make live CONFIG_NAME=redbear-full
|
||||
# QEMU: make all CONFIG_NAME=redbear-full && make qemu
|
||||
#
|
||||
# Extends redbear-mini with the full desktop/graphics stack:
|
||||
# Wayland, Qt6, KF6, KWin, Mesa, DRM drivers, firmware, greeter.
|
||||
|
||||
include = ["redbear-mini.toml"]
|
||||
|
||||
[general]
|
||||
filesystem_size = 4096
|
||||
efi_partition_size = 16
|
||||
|
||||
[users.messagebus]
|
||||
uid = 100
|
||||
gid = 100
|
||||
name = "messagebus"
|
||||
home = "/nonexistent"
|
||||
shell = "/usr/bin/ion"
|
||||
|
||||
[users.root]
|
||||
shell = "/usr/bin/zsh"
|
||||
|
||||
[packages]
|
||||
# Runtime driver parameter control surface.
|
||||
driver-params = {}
|
||||
|
||||
# Firmware loading
|
||||
redbear-firmware = {}
|
||||
firmware-loader = {}
|
||||
|
||||
# NUMA topology discovery (userspace daemon)
|
||||
numad = {}
|
||||
|
||||
# GPU/graphics stack
|
||||
redox-drm = {}
|
||||
mesa = {}
|
||||
libdrm = {}
|
||||
|
||||
libwayland = {}
|
||||
wayland-protocols = {}
|
||||
# redbear-compositor = {}
|
||||
|
||||
# Keyboard/input
|
||||
# libxkbcommon = {} # build needed
|
||||
# xkeyboard-config = {} # build needed
|
||||
libevdev = {}
|
||||
# libinput = {} # WIP: missing libepoll-shim recipe dependency
|
||||
|
||||
# Qt6 stack
|
||||
qtbase = {}
|
||||
qtdeclarative = {}
|
||||
qtsvg = {}
|
||||
qtwayland = {}
|
||||
qt6-wayland-smoke = {}
|
||||
qt6-sensors = {}
|
||||
|
||||
# KF6 Frameworks — explicit real-build surface in alphabetical order
|
||||
# kirigami: blocked (QML gate — QQuickWindow/QQmlEngine headers don't exist on Redox)
|
||||
kf6-kio = {}
|
||||
# kde-cli-tools = {} # blocked: direct repo cook fails
|
||||
|
||||
kdecoration = {}
|
||||
kf6-attica = {}
|
||||
kf6-karchive = {}
|
||||
kf6-kauth = {}
|
||||
kf6-kbookmarks = {}
|
||||
kf6-kcmutils = {}
|
||||
kf6-kcodecs = {}
|
||||
kf6-kcolorscheme = {}
|
||||
kf6-kcompletion = {}
|
||||
kf6-kconfig = {}
|
||||
kf6-kconfigwidgets = {}
|
||||
kf6-kcoreaddons = {}
|
||||
kf6-kcrash = {}
|
||||
kf6-kdbusaddons = {}
|
||||
kf6-kdeclarative = {}
|
||||
kf6-kded6 = {}
|
||||
kf6-kguiaddons = {}
|
||||
kf6-ki18n = {}
|
||||
kf6-kiconthemes = {}
|
||||
kf6-kidletime = {}
|
||||
kf6-kitemmodels = {}
|
||||
kf6-kitemviews = {}
|
||||
kf6-kjobwidgets = {}
|
||||
kf6-knotifications = {}
|
||||
kf6-kpackage = {}
|
||||
kf6-kservice = {}
|
||||
kf6-ktextwidgets = {}
|
||||
kf6-kwayland = {}
|
||||
kf6-kwidgetsaddons = {}
|
||||
kf6-kxmlgui = {}
|
||||
kf6-prison = {}
|
||||
kf6-solid = {}
|
||||
kf6-sonnet = {}
|
||||
kf6-knewstuff = {}
|
||||
kf6-kwallet = {}
|
||||
kglobalacceld = {}
|
||||
|
||||
# kwin = {} # Blocked: Qt6 Wayland plugin import error (QML gate)
|
||||
|
||||
# Plasma + app packages — blocked on kirigami (QML gate)
|
||||
# plasma-framework = {}
|
||||
# plasma-workspace = {}
|
||||
# plasma-desktop = {}
|
||||
|
||||
redbear-authd = {}
|
||||
redbear-session-launch = {}
|
||||
seatd = {}
|
||||
redbear-greeter = {}
|
||||
amdgpu = {}
|
||||
|
||||
# Core Red Bear umbrella package
|
||||
redbear-meta = {}
|
||||
|
||||
# Phase 1 runtime validation tests (POSIX: signalfd, timerfd, eventfd, shm_open, sem_open, waitid)
|
||||
relibc-phase1-tests = {}
|
||||
|
||||
# Desktop fonts and icons
|
||||
dejavu = {}
|
||||
freefont = {}
|
||||
hicolor-icon-theme = {}
|
||||
pop-icon-theme = {}
|
||||
|
||||
# Suppress legacy desktop packages
|
||||
orbdata = "ignore"
|
||||
orbital = "ignore"
|
||||
orbterm = "ignore"
|
||||
orbutils = "ignore"
|
||||
cosmic-edit = "ignore"
|
||||
cosmic-files = "ignore"
|
||||
cosmic-icons = "ignore"
|
||||
cosmic-term = "ignore"
|
||||
curl = "ignore"
|
||||
git = "ignore"
|
||||
mc = "ignore"
|
||||
#curl = "ignore" # suppressed: cascade rebuild
|
||||
#git = "ignore" # suppressed: cascade rebuild
|
||||
#konsole = {} # WIP: recipe exists, not yet built — blocked by libiconv fetch
|
||||
#kf6-pty = {} # WIP: recipe exists, not yet built
|
||||
|
||||
[[files]]
|
||||
path = "/lib/firmware/amdgpu"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o755
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/fonts"
|
||||
data = "/usr/share/fonts"
|
||||
symlink = true
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/05_boot-essential.target"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Boot essential services target"
|
||||
requires_weak = [
|
||||
"00_base.target",
|
||||
]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/13_iommu.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "IOMMU DMA remapping daemon"
|
||||
requires_weak = [
|
||||
"12_boot-late.target",
|
||||
"00_pcid-spawner.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "/usr/bin/iommu"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/12_dbus.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "D-Bus system bus"
|
||||
requires_weak = [
|
||||
"12_boot-late.target",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "dbus-daemon"
|
||||
args = ["--system", "--nopidfile"]
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/13_redbear-sessiond.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Red Bear session broker (org.freedesktop.login1)"
|
||||
requires_weak = [
|
||||
"12_dbus.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "redbear-sessiond"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/13_seatd.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "seatd seat management daemon"
|
||||
requires_weak = [
|
||||
"12_dbus.service",
|
||||
"13_redbear-sessiond.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "/usr/bin/seatd"
|
||||
args = ["-l", "info"]
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/14_redbear-upower.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "UPower D-Bus service (org.freedesktop.UPower)"
|
||||
requires_weak = [
|
||||
"12_dbus.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "redbear-upower"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/14_redbear-udisks.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "UDisks2 D-Bus service (org.freedesktop.UDisks2)"
|
||||
requires_weak = [
|
||||
"12_dbus.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "redbear-udisks"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/14_redbear-polkit.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "PolicyKit1 D-Bus service (org.freedesktop.PolicyKit1)"
|
||||
requires_weak = [
|
||||
"12_dbus.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "redbear-polkit"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/19_redbear-authd.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Red Bear authentication daemon"
|
||||
requires_weak = [
|
||||
"12_dbus.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "/usr/bin/redbear-authd"
|
||||
envs = { QT_PLUGIN_PATH = "/usr/plugins", QT_QPA_PLATFORM_PLUGIN_PATH = "/usr/plugins/platforms", QML2_IMPORT_PATH = "/usr/qml", XCURSOR_THEME = "Pop", XKB_CONFIG_ROOT = "/usr/share/X11/xkb", KWIN_DRM_DEVICES = "/scheme/drm/card0" }
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/20_display.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "KDE session assembly helper"
|
||||
requires_weak = [
|
||||
"12_dbus.service",
|
||||
"13_redbear-sessiond.service",
|
||||
"13_seatd.service",
|
||||
"19_redbear-authd.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "/usr/bin/redbear-session-launch"
|
||||
args = ["--username", "root", "--mode", "session", "--session", "kde-wayland", "--vt", "4", "--runtime-dir", "/tmp/run/redbear-display-session", "--wayland-display", "wayland-display"]
|
||||
envs = { QT_PLUGIN_PATH = "/usr/plugins", QT_QPA_PLATFORM_PLUGIN_PATH = "/usr/plugins/platforms", QML2_IMPORT_PATH = "/usr/qml", XCURSOR_THEME = "Pop", XKB_CONFIG_ROOT = "/usr/share/X11/xkb", REDBEAR_KDE_SESSION_BACKEND = "virtual", REDBEAR_KDE_SESSION_STATE_DIR = "/run/redbear-display-session" }
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/20_greeter.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Red Bear greeter service"
|
||||
requires_weak = [
|
||||
"00_pcid-spawner.service",
|
||||
"12_dbus.service",
|
||||
"13_redbear-sessiond.service",
|
||||
"13_seatd.service",
|
||||
"19_redbear-authd.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "/usr/bin/redbear-greeterd"
|
||||
envs = { VT = "3", REDBEAR_GREETER_USER = "greeter", KWIN_DRM_DEVICES = "/scheme/drm/card0", REDBEAR_DRM_WAIT_SECONDS = "10" }
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/29_activate_console.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Activate fallback console VT"
|
||||
requires_weak = [
|
||||
"05_boot-essential.target",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "inputd"
|
||||
args = ["-A", "2"]
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/30_console.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Console terminals"
|
||||
requires_weak = [
|
||||
"29_activate_console.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "getty"
|
||||
args = ["2"]
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/31_debug_console.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Debug console"
|
||||
requires_weak = [
|
||||
"29_activate_console.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "getty"
|
||||
args = ["/scheme/debug/no-preserve", "-J"]
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[users.greeter]
|
||||
password = ""
|
||||
uid = 101
|
||||
gid = 101
|
||||
name = "greeter"
|
||||
home = "/nonexistent"
|
||||
shell = "/usr/bin/ion"
|
||||
|
||||
[groups.greeter]
|
||||
gid = 101
|
||||
members = ["greeter"]
|
||||
|
||||
[groups.messagebus]
|
||||
gid = 100
|
||||
members = ["messagebus"]
|
||||
|
||||
[[files]]
|
||||
path = "/etc/pcid.d/ihdgd.toml"
|
||||
data = """
|
||||
[[drivers]]
|
||||
name = "Intel GPU (VGA compatible)"
|
||||
class = 0x03
|
||||
vendor = 0x8086
|
||||
subclass = 0x00
|
||||
command = ["redox-drm"]
|
||||
|
||||
[[drivers]]
|
||||
name = "Intel GPU (3D controller)"
|
||||
class = 0x03
|
||||
vendor = 0x8086
|
||||
subclass = 0x02
|
||||
command = ["redox-drm"]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/pcid.d/virtio-gpud.toml"
|
||||
data = """
|
||||
[[drivers]]
|
||||
name = "VirtIO GPU"
|
||||
class = 0x03
|
||||
vendor = 0x1af4
|
||||
subclass = 0x00
|
||||
command = ["redox-drm"]
|
||||
"""
|
||||
@@ -0,0 +1,127 @@
|
||||
# Red Bear greeter/login service wiring
|
||||
#
|
||||
# This fragment is intended to be included by the active desktop/graphics target.
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/05_boot-essential.target"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Boot essential services target"
|
||||
requires_weak = [
|
||||
"00_base.target",
|
||||
]
|
||||
"""
|
||||
|
||||
[users.greeter]
|
||||
password = ""
|
||||
uid = 101
|
||||
gid = 101
|
||||
name = "greeter"
|
||||
home = "/nonexistent"
|
||||
shell = "/usr/bin/ion"
|
||||
|
||||
[groups.greeter]
|
||||
gid = 101
|
||||
members = ["greeter"]
|
||||
|
||||
[packages]
|
||||
redbear-authd = {}
|
||||
redbear-session-launch = {}
|
||||
redbear-greeter = {}
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/19_redbear-authd.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Red Bear authentication daemon"
|
||||
requires_weak = [
|
||||
"12_dbus.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "redbear-authd"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/20_display.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Compositor proof (Phase 2: KWin virtual + Qt6 smoke + 60s survival)"
|
||||
requires_weak = [
|
||||
"12_dbus.service",
|
||||
"13_redbear-sessiond.service",
|
||||
"13_seatd.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "redbear-validation-session"
|
||||
envs = { VT = "3" }
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/20_greeter.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Red Bear greeter service (experimental — Phase 3 user session bring-up)"
|
||||
requires_weak = [
|
||||
"00_pcid-spawner.service",
|
||||
"12_dbus.service",
|
||||
"13_redbear-sessiond.service",
|
||||
"13_seatd.service",
|
||||
"19_redbear-authd.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "/usr/bin/redbear-greeterd"
|
||||
envs = { VT = "3", REDBEAR_GREETER_USER = "greeter", KWIN_DRM_DEVICES = "/scheme/drm/card0", REDBEAR_DRM_WAIT_SECONDS = "10" }
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/30_console.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Console terminals"
|
||||
requires_weak = [
|
||||
"29_activate_console.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "getty"
|
||||
args = ["2"]
|
||||
type = "oneshot_async"
|
||||
respawn = true
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/29_activate_console.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Activate fallback console VT"
|
||||
requires_weak = [
|
||||
"05_boot-essential.target",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "inputd"
|
||||
args = ["-A", "2"]
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/31_debug_console.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Debug console"
|
||||
requires_weak = [
|
||||
"29_activate_console.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "getty"
|
||||
args = ["/scheme/debug/no-preserve", "-J"]
|
||||
type = "oneshot_async"
|
||||
respawn = true
|
||||
"""
|
||||
@@ -0,0 +1,9 @@
|
||||
# Red Bear OS shared GRUB policy fragment
|
||||
# Use with any redbear-* profile to make GRUB first-class in installer flows.
|
||||
|
||||
[general]
|
||||
bootloader = "grub"
|
||||
efi_partition_size = 16
|
||||
|
||||
[packages]
|
||||
grub = {}
|
||||
@@ -0,0 +1,16 @@
|
||||
# Red Bear OS GRUB Configuration
|
||||
# Text-only ISO with GRUB boot manager for bare metal.
|
||||
#
|
||||
# Build: make live CONFIG_NAME=redbear-grub
|
||||
#
|
||||
# Identical to redbear-mini but uses GNU GRUB as the boot manager
|
||||
# instead of the Redox EFI bootloader.
|
||||
|
||||
include = ["redbear-mini.toml", "redbear-grub-policy.toml"]
|
||||
|
||||
[general]
|
||||
bootloader = "grub"
|
||||
efi_partition_size = 16
|
||||
|
||||
[packages]
|
||||
grub = {}
|
||||
@@ -0,0 +1,51 @@
|
||||
# Red Bear OS overrides for base init services.
|
||||
#
|
||||
# 00_base.service: stripped base setup (tmpdir only, no sudo — sudo runs from
|
||||
# base.toml's 00_sudo.service). ipcd and ptyd are started by
|
||||
# 00_ipcd.service and 00_ptyd.service from the base recipe.
|
||||
# 00_drivers / 10_net: no longer overridden — the legacy scripts were removed
|
||||
# from base.toml. The retained 00_pcid-spawner.service unit name now
|
||||
# launches driver-manager so existing init ordering remains stable.
|
||||
# 00_pcid-spawner.service: compatibility wrapper for driver-manager. The base
|
||||
# recipe uses type="oneshot" which blocks init until pcid-spawner exits.
|
||||
# Running driver-manager here with oneshot_async keeps the historic unit
|
||||
# name for downstream `requires_weak` consumers while moving PCI driver
|
||||
# spawning to the manager that performs bind/channel handoff.
|
||||
|
||||
[packages]
|
||||
zsh = {}
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/00_base.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Base environment setup (tmpdir)"
|
||||
|
||||
[service]
|
||||
cmd = "ion"
|
||||
args = ["-c", "rm -rf /tmp; mkdir -m a=rwxt /tmp"]
|
||||
type = "oneshot"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/init.d/20_audiod.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Audio multiplexer"
|
||||
default_dependencies = false
|
||||
|
||||
[service]
|
||||
cmd = "audiod"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/init.d/00_pcid-spawner.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "PCI driver spawner"
|
||||
|
||||
[service]
|
||||
cmd = "pcid-spawner"
|
||||
type = "oneshot"
|
||||
"""
|
||||
@@ -0,0 +1,20 @@
|
||||
# Red Bear OS overrides for legacy desktop init services.
|
||||
# Blank the display and console services inherited from desktop-minimal.toml.
|
||||
# These intentional empty overrides prevent the inherited services from launching;
|
||||
# the active redbear-full config provides its own display/console/greeter services.
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/20_display.service"
|
||||
data = ""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/29_activate_console.service"
|
||||
data = ""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/30_console.service"
|
||||
data = ""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/31_debug_console.service"
|
||||
data = ""
|
||||
@@ -0,0 +1,467 @@
|
||||
# Red Bear OS Mini Configuration
|
||||
# Text-only ISO for console/recovery/install on bare metal.
|
||||
#
|
||||
# Build: make live CONFIG_NAME=redbear-mini
|
||||
#
|
||||
# Target contract:
|
||||
# - text-login live/recovery/install surface
|
||||
# - boot framebuffer for VT text consoles via vesad + fbcond
|
||||
# - all non-graphics, non-firmware packages from the full profile
|
||||
# - no linux-firmware payload, no firmware-loader, no GPU/display drivers
|
||||
|
||||
include = ["minimal.toml", "redbear-legacy-base.toml", "redbear-netctl.toml", "redbear-device-services.toml"]
|
||||
|
||||
[general]
|
||||
filesystem_size = 1536
|
||||
|
||||
[users.messagebus]
|
||||
uid = 100
|
||||
gid = 100
|
||||
name = "messagebus"
|
||||
home = "/nonexistent"
|
||||
shell = "/usr/bin/ion"
|
||||
|
||||
[packages]
|
||||
# Red Bear OS branding and host utilities.
|
||||
redbear-release = {}
|
||||
redbear-hwutils = {}
|
||||
redbear-quirks = {}
|
||||
|
||||
# Device driver infrastructure (pcid-spawner is built by the base recipe;
|
||||
# driver-manager requires driver config migration and is not yet ready)
|
||||
ehcid = {}
|
||||
ohcid = {}
|
||||
uhcid = {}
|
||||
|
||||
# Redox-native netctl tooling.
|
||||
redbear-netctl = {}
|
||||
redbear-netctl-console = {}
|
||||
redbear-netstat = {}
|
||||
redbear-traceroute = {}
|
||||
redbear-mtr = {}
|
||||
redbear-nmap = {}
|
||||
|
||||
# Wi-Fi control daemon (firmware-loader excluded — no firmware blobs in mini).
|
||||
redbear-wifictl = {}
|
||||
|
||||
# Diagnostics and shell-side utilities.
|
||||
mc = "ignore"
|
||||
redbear-info = {}
|
||||
|
||||
# Keep package builder utility in live environment.
|
||||
cub = {}
|
||||
cpufreqd = {}
|
||||
thermald = {}
|
||||
hwrngd = {}
|
||||
redbear-acmd = {}
|
||||
redbear-ecmd = {}
|
||||
redbear-usbaudiod = {}
|
||||
driver-params = {}
|
||||
|
||||
# ── PCI device database (critical for PCI driver matching) ──
|
||||
pciids = {}
|
||||
|
||||
# ── Filesystem support ──
|
||||
ext4d = {}
|
||||
fatd = {}
|
||||
redoxfs = {}
|
||||
|
||||
# ── System installer ──
|
||||
installer = {}
|
||||
|
||||
# ── Input / device management ──
|
||||
evdevd = {}
|
||||
udev-shim = {}
|
||||
|
||||
# ── D-Bus IPC and session services ──
|
||||
dbus = {}
|
||||
redbear-sessiond = {}
|
||||
redbear-dbus-services = {}
|
||||
redbear-notifications = {}
|
||||
redbear-upower = {}
|
||||
redbear-udisks = {}
|
||||
redbear-polkit = {}
|
||||
|
||||
# ── IOMMU DMA remapping ──
|
||||
iommu = {}
|
||||
|
||||
# ── Standard CLI tools (from server profile) ──
|
||||
bash = {}
|
||||
bottom = {}
|
||||
#curl = {} # suppressed: nghttp2 dependency chain fails; curl not needed for boot/recovery
|
||||
diffutils = {}
|
||||
findutils = {}
|
||||
#git = {} # suppressed: cascading rebuild; git not needed for boot/recovery
|
||||
htop = {}
|
||||
#mc = {} # suppressed: C99 format warning errors in compilation
|
||||
|
||||
# ── Build / packaging utilities ──
|
||||
# patchelf = {} # requires strtold which is missing in relibc
|
||||
shared-mime-info = {}
|
||||
|
||||
# VT/getty/login chain: initfs starts inputd + vesad + fbcond in phase 1,
|
||||
# then minimal.toml legacy 30_console runs inputd -A 2 + getty 2 + getty debug.
|
||||
|
||||
[[files]]
|
||||
path = "/etc/netctl/active"
|
||||
data = "wired-dhcp\n"
|
||||
|
||||
[[files]]
|
||||
path = "/etc/init.d/10_smolnetd.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Network stack (non-blocking on live-mini)"
|
||||
requires_weak = [
|
||||
"00_pcid-spawner.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "netstack"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/init.d/10_dhcpd.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "DHCP client daemon (non-blocking on live-mini)"
|
||||
requires_weak = [
|
||||
"10_smolnetd.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "dhcpd"
|
||||
args = ["-f"]
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/issue"
|
||||
data = """
|
||||
########## Red Bear OS #########
|
||||
# Login with the following: #
|
||||
# `user` #
|
||||
# `root`:`password` #
|
||||
################################
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/motd"
|
||||
data = """
|
||||
|
||||
_ _
|
||||
| | (_)
|
||||
| | ___ _ ___ _ __ _ _ ___
|
||||
| |/ / || |/ _ \\ | '_ \\| | | / __|
|
||||
| < | || | (_) || |_) | |_| \\__ \\
|
||||
|_|\\_\\|_|/ |\\___/ | .__/ \\__,_|___/
|
||||
|__/ | |
|
||||
|_|
|
||||
|
||||
Red Bear OS v0.2.0 "Liliya" — Built on Redox OS
|
||||
Type 'help' for available commands.
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/init.d/20_audiod.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Audio multiplexer (non-blocking on live-mini)"
|
||||
requires_weak = [
|
||||
"00_base.target",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "audiod"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/init.d/02_serial_probe.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Serial boot probe marker"
|
||||
requires_weak = [
|
||||
"00_base.target",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "echo"
|
||||
args = ["RB_SERIAL_PROBE_OK"]
|
||||
type = "oneshot"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/init.d/00_gpiod.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "GPIO controller registry (non-blocking on live-mini)"
|
||||
requires_weak = [
|
||||
"00_base.target",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "gpiod"
|
||||
type = { scheme = "gpio" }
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/init.d/00_i2cd.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "I2C adapter registry (non-blocking on live-mini)"
|
||||
requires_weak = [
|
||||
"00_base.target",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "i2cd"
|
||||
type = { scheme = "i2c" }
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/init.d/00_i2c-dw-acpi.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "DesignWare ACPI I2C controller (non-blocking)"
|
||||
requires_weak = [
|
||||
"00_i2cd.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "dw-acpi-i2cd"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/init.d/00_intel-gpiod.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Intel ACPI GPIO registrar (non-blocking)"
|
||||
requires_weak = [
|
||||
"00_gpiod.service",
|
||||
"00_i2cd.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "intel-gpiod"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/init.d/00_i2c-gpio-expanderd.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "I2C GPIO expander companion bridge (non-blocking on live-mini)"
|
||||
requires_weak = [
|
||||
"00_i2cd.service",
|
||||
"00_gpiod.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "i2c-gpio-expanderd"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/init.d/00_i2c-hidd.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "ACPI I2C HID bring-up daemon (non-blocking)"
|
||||
requires_weak = [
|
||||
"00_i2cd.service",
|
||||
"00_i2c-dw-acpi.service",
|
||||
"00_intel-gpiod.service",
|
||||
"00_i2c-gpio-expanderd.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "i2c-hidd"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/init.d/00_ucsid.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "USB-C UCSI topology detector (non-blocking on live-mini)"
|
||||
requires_weak = [
|
||||
"00_base.target",
|
||||
"00_i2cd.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "ucsid"
|
||||
type = { scheme = "ucsi" }
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/12_boot-late.target"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Late boot services target"
|
||||
requires_weak = [
|
||||
"00_base.target",
|
||||
]
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/11_udev.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "udev compatibility shim"
|
||||
requires_weak = [
|
||||
"12_boot-late.target",
|
||||
"00_pcid-spawner.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "udev-shim"
|
||||
type = { scheme = "udev" }
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/10_evdevd.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Evdev input daemon"
|
||||
requires_weak = [
|
||||
"12_boot-late.target",
|
||||
"00_pcid-spawner.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "evdevd"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/11_wifictl.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Wi-Fi control daemon"
|
||||
requires_weak = [
|
||||
"12_boot-late.target",
|
||||
"00_pcid-spawner.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "redbear-wifictl"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/12_dbus.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "D-Bus system bus"
|
||||
requires_weak = [
|
||||
"12_boot-late.target",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "dbus-daemon"
|
||||
args = ["--system"]
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/13_redbear-sessiond.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Red Bear session broker (org.freedesktop.login1)"
|
||||
requires_weak = [
|
||||
"12_dbus.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "redbear-sessiond"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/13_iommu.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "IOMMU DMA remapping daemon"
|
||||
requires_weak = [
|
||||
"12_boot-late.target",
|
||||
"00_pcid-spawner.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "/usr/bin/iommu"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/14_redbear-upower.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "UPower D-Bus service (org.freedesktop.UPower)"
|
||||
requires_weak = [
|
||||
"12_dbus.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "redbear-upower"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/14_redbear-udisks.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "UDisks2 D-Bus service (org.freedesktop.UDisks2)"
|
||||
requires_weak = [
|
||||
"12_dbus.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "redbear-udisks"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/14_redbear-polkit.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "PolicyKit1 D-Bus service (org.freedesktop.PolicyKit1)"
|
||||
requires_weak = [
|
||||
"12_dbus.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "redbear-polkit"
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/var/lib/dbus"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o755
|
||||
|
||||
[[files]]
|
||||
path = "/run/dbus"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o755
|
||||
|
||||
[[files]]
|
||||
path = "/etc/pcid.d/ihdgd.toml"
|
||||
data = """
|
||||
# redbear-live-mini: text-only image; override upstream ihdgd config with empty file
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/pcid.d/virtio-gpud.toml"
|
||||
data = """
|
||||
# redbear-live-mini: text-only image; override upstream virtio-gpud config with empty file
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/pcid.d/00_text_mode_gpu_mask.toml"
|
||||
data = """
|
||||
# redbear-live-mini: no display driver matched; class 0x03 devices are skipped
|
||||
"""
|
||||
@@ -0,0 +1,106 @@
|
||||
# Red Bear OS shared network profile wiring
|
||||
#
|
||||
# Shared by redbear-minimal, redbear-desktop, redbear-full, and redbear-kde.
|
||||
|
||||
[[files]]
|
||||
path = "/etc/netctl"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o755
|
||||
|
||||
[[files]]
|
||||
path = "/etc/netctl/examples"
|
||||
data = ""
|
||||
directory = true
|
||||
mode = 0o755
|
||||
|
||||
[[files]]
|
||||
path = "/etc/netctl/examples/wired-dhcp"
|
||||
data = """
|
||||
Description='Red Bear wired DHCP profile'
|
||||
Interface=eth0
|
||||
Connection=ethernet
|
||||
IP=dhcp
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/netctl/wired-dhcp"
|
||||
data = """
|
||||
Description='Red Bear wired DHCP profile'
|
||||
Interface=eth0
|
||||
Connection=ethernet
|
||||
IP=dhcp
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/netctl/examples/wired-static"
|
||||
data = """
|
||||
Description='Red Bear wired static profile'
|
||||
Interface=eth0
|
||||
Connection=ethernet
|
||||
IP=static
|
||||
Address=('192.168.1.10/24')
|
||||
Gateway='192.168.1.1'
|
||||
DNS=('1.1.1.1')
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/netctl/examples/wifi-dhcp"
|
||||
data = """
|
||||
Description='Red Bear Wi-Fi DHCP profile'
|
||||
Interface=wlan0
|
||||
Connection=wifi
|
||||
SSID='example-ssid'
|
||||
Security=wpa2-psk
|
||||
Key='example-passphrase'
|
||||
IP=dhcp
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/netctl/examples/wifi-open"
|
||||
data = """
|
||||
Description='Red Bear Wi-Fi open-network profile'
|
||||
Interface=wlan0
|
||||
Connection=wifi
|
||||
SSID='example-open-ssid'
|
||||
Security=open
|
||||
IP=dhcp
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/netctl/examples/wifi-open-bounded"
|
||||
data = """
|
||||
Description='Red Bear Wi-Fi bounded lifecycle profile'
|
||||
Interface=wlan0
|
||||
Connection=wifi
|
||||
SSID='example-open-ssid'
|
||||
Security=open
|
||||
IP=bounded
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/etc/netctl/wifi-open-bounded"
|
||||
data = """
|
||||
Description='Red Bear Wi-Fi bounded lifecycle profile'
|
||||
Interface=wlan0
|
||||
Connection=wifi
|
||||
SSID='example-open-ssid'
|
||||
Security=open
|
||||
IP=bounded
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/12_netctl.service"
|
||||
data = """
|
||||
[unit]
|
||||
description = "Network profile application"
|
||||
requires_weak = [
|
||||
"10_smolnetd.service",
|
||||
"10_dhcpd.service",
|
||||
]
|
||||
|
||||
[service]
|
||||
cmd = "redbear-netctl"
|
||||
args = ["--boot"]
|
||||
type = "oneshot_async"
|
||||
"""
|
||||
@@ -0,0 +1,20 @@
|
||||
# Red Bear OS Wi-Fi Experimental Profile
|
||||
#
|
||||
# Standalone tracked build target for the current bounded Intel Wi-Fi slice.
|
||||
#
|
||||
# This profile extends the existing minimal Red Bear baseline but switches the default active profile
|
||||
# to the bounded Wi-Fi path and adds the first Intel driver-side package on top of the shared
|
||||
# firmware/control/profile tooling.
|
||||
|
||||
include = ["redbear-minimal.toml"]
|
||||
|
||||
[general]
|
||||
filesystem_size = 2048
|
||||
|
||||
[packages]
|
||||
# First bounded Intel driver-side package
|
||||
redbear-iwlwifi = {}
|
||||
|
||||
[[files]]
|
||||
path = "/etc/netctl/active"
|
||||
data = "wifi-open-bounded\n"
|
||||
@@ -0,0 +1,385 @@
|
||||
# Red Bear OS 0.1.0 Release Manifest
|
||||
# Generated: vie 01 may 2026 10:31:16 WEST
|
||||
# Build system: f55acba68
|
||||
|
||||
# Total: 404 recipes (139 git, 165 tar)
|
||||
|
||||
archives/lz4 tar=https://github.com/lz4/lz4/releases/download/v1.10.0/lz4-1.10.0.tar.gz blake3=3e69fd475e7852e17594985528b5232afeba7d3d56cfebe2e89071768b2ab36a
|
||||
archives/zstd tar=https://github.com/facebook/zstd/releases/download/v1.5.7/zstd-1.5.7.tar.gz blake3=730dca31244abd219e995f03a55d95b2cfb4b3e16cda055a79fa6f30a4f0e1db
|
||||
artwork/pop-wallpapers git=https://github.com/pop-os/wallpapers rev=
|
||||
artwork/ubuntu-wallpapers tar=https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/ubuntu-wallpapers/23.10.4/ubuntu-wallpapers_23.10.4.orig.tar.gz blake3=1e479d0aa48fe3f2961a2dac28c3ed397a29616cf6e7d73f5ceb6fabfd6449e1
|
||||
branding/redbear-release path=source
|
||||
core/base git=https://gitlab.redox-os.org/redox-os/base.git rev=463f76b9608a896e6f6c9f63457f57f6409873c7
|
||||
core/base-initfs same_as=../base
|
||||
core/binutils git=https://gitlab.redox-os.org/redox-os/binutils.git rev=
|
||||
core/bootloader git=https://gitlab.redox-os.org/redox-os/bootloader.git rev=b22a35c
|
||||
core/contain git=https://gitlab.redox-os.org/redox-os/contain.git rev=
|
||||
core/coreutils git=https://gitlab.redox-os.org/redox-os/coreutils.git rev=5559e20
|
||||
core/dash git=https://gitlab.redox-os.org/redox-os/dash.git rev=
|
||||
core/ext4d path=source
|
||||
core/extrautils git=https://gitlab.redox-os.org/redox-os/extrautils.git rev=fb66941
|
||||
core/fatd path=source
|
||||
core/findutils git=https://gitlab.redox-os.org/redox-os/findutils.git rev=116c044
|
||||
core/grub tar=https://ftp.gnu.org/gnu/grub/grub-2.12.tar.xz blake3=13c48453f9becf4a6e49618749dc7cb83a2c4a0d7600eeeadc6c7c2772c0b877
|
||||
core/installer git=https://gitlab.redox-os.org/redox-os/installer.git rev=948bfdc
|
||||
core/ion git=https://gitlab.redox-os.org/redox-os/ion.git rev=1440704f
|
||||
core/kernel git=https://gitlab.redox-os.org/redox-os/kernel.git rev=866dfad
|
||||
core/netdb git=https://gitlab.redox-os.org/redox-os/netdb.git rev=2c15606
|
||||
core/netutils git=https://gitlab.redox-os.org/redox-os/netutils.git rev=40a573b
|
||||
core/pkgar git=https://gitlab.redox-os.org/redox-os/pkgar.git rev=
|
||||
core/pkgutils git=https://gitlab.redox-os.org/redox-os/pkgutils.git rev=70c5067
|
||||
core/profiled git=https://gitlab.redox-os.org/redox-os/profiled.git rev=
|
||||
core/redoxfs git=https://gitlab.redox-os.org/redox-os/redoxfs.git rev=b596776
|
||||
core/relibc git=https://gitlab.redox-os.org/redox-os/relibc.git rev=861bbb0
|
||||
core/strace git=https://gitlab.redox-os.org/redox-os/strace-redox.git rev=
|
||||
core/userutils git=https://gitlab.redox-os.org/redox-os/userutils.git rev=0c5274f
|
||||
core/uutils git=https://github.com/uutils/coreutils rev=1f7c81f5d2d3e56c518349c0392158871a1ea9ec
|
||||
demos/cmatrix git=https://github.com/abishekvashok/cmatrix rev=
|
||||
demos/cpal git=https://gitlab.redox-os.org/redox-os/cpal.git rev=
|
||||
demos/dynamic-example git=https://gitlab.redox-os.org/redox-os/dynamic-example.git rev=
|
||||
demos/exampled git=https://gitlab.redox-os.org/redox-os/exampled.git rev=
|
||||
demos/glutin git=https://gitlab.redox-os.org/redox-os/glutin.git rev=
|
||||
demos/iced git=https://gitlab.redox-os.org/redox-os/iced.git rev=
|
||||
demos/orbclient git=https://gitlab.redox-os.org/redox-os/orbclient.git rev=
|
||||
demos/pixelcannon git=https://github.com/jackpot51/pixelcannon.git rev=
|
||||
demos/winit git=https://github.com/pop-os/winit.git rev=
|
||||
dev/autoconf tar=https://ftp.gnu.org/gnu/autoconf/autoconf-2.71.tar.xz blake3=da1cc8af8551c343de9f42af0ae53fd7dff3623487157623892b6cd7e3bb5692
|
||||
dev/automake tar=https://ftp.gnu.org/gnu/automake/automake-1.16.5.tar.xz blake3=f42cfc333aaaa11f2bcb05b5b0273b8706c820c22f9ba4367f7eb920551695cd
|
||||
dev/binutils-gdb git=https://gitlab.redox-os.org/redox-os/binutils-gdb rev=
|
||||
dev/clang21 same_as=../llvm21
|
||||
dev/cmake tar=https://github.com/Kitware/CMake/releases/download/v4.0.3/cmake-4.0.3.tar.gz blake3=
|
||||
dev/crates-io-index git=https://github.com/rust-lang/crates.io-index.git rev=
|
||||
dev/fontconfig tar=https://www.freedesktop.org/software/fontconfig/release/fontconfig-2.16.0.tar.xz blake3=5c95d48f5b9150f4a06d8acac12c25edaac956007df95a3bf527df02a5908f0e
|
||||
dev/gcc13 git=https://gitlab.redox-os.org/redox-os/gcc rev=8e365ce7e5
|
||||
dev/gdbserver git=https://gitlab.redox-os.org/redox-os/gdbserver.git rev=
|
||||
dev/gdk-pixbuf tar=https://ftp.gnome.org/pub/gnome/sources/gdk-pixbuf/2.44/gdk-pixbuf-2.44.4.tar.xz blake3=94db7bebffbd6be84a1b58a05771e411e9f7c16b06d73fcedaf0e6c0e552be9c
|
||||
dev/git tar=https://www.kernel.org/pub/software/scm/git/git-2.13.1.tar.xz blake3=bc78271bffd60c5b8b938d8c08fd74dc2de8d21fbaf8f8e0e3155436d9263f17
|
||||
dev/gitoxide git=https://github.com/Byron/gitoxide.git rev=
|
||||
dev/gnu-make tar=http://ftp.gnu.org/gnu/make/make-4.4.tar.gz blake3=1a0e5353205e106bd9b3c0f4a5f37ee1156a1e1c8feb771d1b4842c216612cba
|
||||
dev/hello-world-examples git=https://github.com/leachim6/hello-world rev=
|
||||
dev/jq tar=https://github.com/jqlang/jq/releases/download/jq-1.8.1/jq-1.8.1.tar.gz blake3=
|
||||
dev/lci git=https://github.com/jD91mZM2/rust-lci rev=
|
||||
dev/libtool git=https://gitlab.redox-os.org/redox-os/libtool rev=
|
||||
dev/lld21 same_as=../llvm21
|
||||
dev/llvm18 git=https://gitlab.redox-os.org/redox-os/llvm-project.git rev=
|
||||
dev/llvm21 git=https://gitlab.redox-os.org/redox-os/llvm-project.git rev=250d0b022e
|
||||
dev/lua54 tar=https://lua.org/ftp/lua-5.4.7.tar.gz blake3=e51c2f347e3185479d5ff95cae8ac77511db486853269443c56bedaa0a6ae629
|
||||
dev/luajit git=https://luajit.org/git/luajit.git rev=a4f56a459a588ae768801074b46ba0adcfb49eb1
|
||||
dev/luarocks git=https://github.com/luarocks/luarocks.git rev=
|
||||
dev/nasm tar=https://gstreamer.freedesktop.org/src/mirror/nasm-2.14.02.tar.xz blake3=f66c0cc852c3b9e3321f57c33ef336e17a128bd3d854ee095aae7e6f64629f20
|
||||
dev/patch tar=https://ftp.gnu.org/gnu/patch/patch-2.7.6.tar.xz blake3=d46d14c12aa4ea51e356bf92091c368fd871e1d770b94bc29027886737aecd5f
|
||||
dev/pciids git=https://github.com/pciutils/pciids.git rev=1f4ff7c
|
||||
dev/php84 tar=https://www.php.net/distributions/php-8.4.17.tar.xz blake3=a8478dddd948d4b26e51c5727ac0895440da76e8ad9be947098a4284ca0b7f2a
|
||||
dev/pkg-config tar=https://pkg-config.freedesktop.org/releases/pkg-config-0.29.2.tar.gz blake3=713372b09a1fafeec130dc9bf812a3880f2a90496af5d2194e508d91ccf667d0
|
||||
dev/python312 tar=https://www.python.org/ftp/python/3.12.12/Python-3.12.12.tar.xz blake3=29636fdae3e0ee8d0fe585e528c9376fe43876f5f3f0f7892140567946fd907b
|
||||
dev/redoxer git=https://gitlab.redox-os.org/redox-os/redoxer rev=
|
||||
dev/rust git=https://gitlab.redox-os.org/redox-os/rust.git rev=
|
||||
dev/rustpython git=https://github.com/RustPython/RustPython rev=2025-10-13-main-51
|
||||
doc/book git=https://gitlab.redox-os.org/redox-os/book.git rev=
|
||||
drivers/ehcid path=source
|
||||
drivers/linux-kpi path=source
|
||||
drivers/ohcid path=source
|
||||
drivers/redbear-btusb path=source
|
||||
drivers/redbear-iwlwifi path=source
|
||||
drivers/redox-driver-core path=source
|
||||
drivers/redox-driver-pci path=source
|
||||
drivers/redox-driver-sys path=source
|
||||
drivers/uhcid path=source
|
||||
drivers/usb-core path=source
|
||||
emulators/dosbox tar=https://sourceforge.net/projects/dosbox/files/dosbox/0.74-3/dosbox-0.74-3.tar.gz/download blake3=8bc50ffdba20579fb3080a0dca32cb939c8a3c19259aed026482c6ac069b0007
|
||||
emulators/flycast git=https://github.com/jackpot51/flycast.git rev=
|
||||
emulators/libretro-super git=https://github.com/jackpot51/libretro-super.git rev=
|
||||
emulators/mednafen tar=https://mednafen.github.io/releases/files/mednafen-1.29.0.tar.xz blake3=c75c1044cdc9328b2349915a67972d6135c77eb53eb0d995788f22b7daacf79b
|
||||
emulators/mgba tar=https://github.com/mgba-emu/mgba/archive/0.10.5.tar.gz blake3=a1b9e797a5058f5264d276805aef5643b7ea460916e491a0098ba32d87f1519e
|
||||
emulators/retroarch git=https://github.com/jackpot51/retroarch.git rev=
|
||||
emulators/rs-nes git=https://gitlab.redox-os.org/redox-os/rs-nes.git rev=
|
||||
emulators/rust64 git=https://gitlab.redox-os.org/redox-os/rust64.git rev=
|
||||
emulators/rustual-boy git=https://gitlab.redox-os.org/redox-os/rustual-boy.git rev=
|
||||
emulators/rvvm git=https://github.com/LekKit/RVVM.git rev=
|
||||
emulators/scummvm tar=https://downloads.scummvm.org/frs/scummvm/2.0.0/scummvm-2.0.0.tar.xz blake3=02e6791fd43ad3cb4238c07d23350ca1459a0f692689e585dba1d46648f64327
|
||||
files/hf git=https://github.com/sorairolake/hf rev=
|
||||
fonts/dejavu tar=http://sourceforge.net/projects/dejavu/files/dejavu/2.37/dejavu-fonts-ttf-2.37.tar.bz2 blake3=b702bac8a0f8e0802758549da3b4d8041c3c83c3894e1e8a960eab53af18cce8
|
||||
fonts/freefont tar=https://ftp.gnu.org/gnu/freefont/freefont-otf-20120503.tar.gz blake3=e950397741d84981106cf648fbc143c7827b61d637c86c916232d47aabdfe253
|
||||
fonts/ibm-plex tar=https://github.com/IBM/plex/archive/refs/tags/v6.3.0.tar.gz blake3=6c67f5bf8069762eea1e31f5cca5b4e6f57ea1151b34b338046c7976072ccdef
|
||||
fonts/intel-one-mono tar=https://github.com/intel/intel-one-mono/archive/refs/tags/V1.3.0.tar.gz blake3=9caff71b0a9fe8627253c55889964612ea4ae144584a283cd2fe88b7a14a4140
|
||||
fonts/noto-color-emoji git=https://github.com/googlefonts/noto-emoji rev=e8073ab740292f8d5f19b5de144087ac58044d06
|
||||
fonts/ttf-hack tar=https://github.com/source-foundry/Hack/releases/download/v3.003/Hack-v3.003-ttf.tar.xz blake3=acd40f61f6f512b0808d4bf530ab4aeb5a8ec3aa1f65bf5a1d08964d1bc3d044
|
||||
games/classicube git=https://github.com/jackpot51/ClassiCube.git rev=
|
||||
games/devilutionx tar=https://github.com/diasurgical/devilutionX/archive/refs/tags/1.5.4.tar.gz blake3=d4a61ff3a7c69d86a29158918aad48ab9c4866c6a22a3e8da5feadbb7d23b3ca
|
||||
games/eduke32 tar=https://dukeworld.com/eduke32/synthesis/20181010-7067/eduke32_src_20181010-7067.tar.xz blake3=b0b759fe9ca51849f42669e4832ae1ae1f9ad7938529769108f7cf6a6a176558
|
||||
games/freeciv tar=https://files.freeciv.org/stable/freeciv-3.1.4.tar.xz blake3=212630af5e50fb72662ca62a71cdd57318d0cf309b53e46377dd24c8199923a4
|
||||
games/freedoom git=https://gitlab.redox-os.org/redox-os/freedoom.git rev=
|
||||
games/game-2048 git=https://gitlab.redox-os.org/redox-os/2048-rs.git rev=
|
||||
games/gigalomania git=https://gitlab.redox-os.org/redox-os/gigalomania.git rev=
|
||||
games/hematite git=https://gitlab.redox-os.org/redox-os/hematite.git rev=
|
||||
games/neverball tar=https://neverball.org/neverball-1.6.0.tar.gz blake3=74f3b68595f475e89fd2ca8b5fc349837ff36fbbe141f321dfc232dbf8fccf51
|
||||
games/neverball-sols same_as=../neverball
|
||||
games/openjazz tar=https://github.com/AlisterT/openjazz/archive/refs/tags/20240919.tar.gz blake3=c419066dd7bf50510c5ef0746fc47450ab8f5a17a0010a1bc0ad67d0e63538da
|
||||
games/openjk git=https://github.com/jackpot51/OpenJK rev=
|
||||
games/openttd git=https://github.com/OpenTTD/OpenTTD.git rev=231402fb4bea0a0d6a16cef90764d9e7aa699c53
|
||||
games/openttd-opengfx git=https://gitlab.redox-os.org/redox-os/openttd-opengfx.git rev=
|
||||
games/openttd-openmsx git=https://gitlab.redox-os.org/redox-os/openttd-openmsx.git rev=
|
||||
games/openttd-opensfx git=https://gitlab.redox-os.org/redox-os/openttd-opensfx.git rev=
|
||||
games/opentyrian git=https://github.com/opentyrian/opentyrian rev=
|
||||
games/prboom tar=https://downloads.sourceforge.net/project/prboom/prboom%20stable/2.5.0/prboom-2.5.0.tar.gz blake3=24c1b9b5aa15fd73e59162055f2c6d8faa82759b76ddfca9828cd2a5c8dc6b2a
|
||||
games/quakespasm git=https://github.com/sezero/quakespasm rev=cc32abe09ed417ce3be10af300d2dc2f686349ba
|
||||
games/redox-games git=https://gitlab.redox-os.org/redox-os/games.git rev=
|
||||
games/sm64ex git=https://github.com/jackpot51/sm64ex.git rev=
|
||||
games/sopwith tar=https://github.com/fragglet/sdl-sopwith/releases/download/sdl-sopwith-1.8.4/sopwith-1.8.4.tar.gz blake3=44e1404a9c4bea257d7778d2a4b1512231603a74b0a7b18eac5d18f36730ed3e
|
||||
games/spacecadetpinball git=https://gitlab.redox-os.org/xTibor/SpaceCadetPinball.git rev=
|
||||
gpu/amdgpu path=source
|
||||
gpu/redox-drm path=source
|
||||
graphics/procedural-wallpapers-rs git=https://github.com/lukas-kirschner/procedural-wallpapers-rs.git rev=
|
||||
gui/installer-gui git=https://gitlab.redox-os.org/redox-os/installer-gui.git rev=
|
||||
gui/orbdata git=https://gitlab.redox-os.org/redox-os/orbdata.git rev=
|
||||
gui/orbital git=https://gitlab.redox-os.org/redox-os/orbital.git rev=
|
||||
gui/orbterm git=https://gitlab.redox-os.org/redox-os/orbterm.git rev=
|
||||
gui/orbutils git=https://gitlab.redox-os.org/redox-os/orbutils.git rev=
|
||||
gui/orbutils-background same_as=../orbutils
|
||||
icons/cosmic-icons git=https://github.com/pop-os/cosmic-icons.git rev=f93dcdfa1060c2cf3f8cf0b56b0338292edcafa5
|
||||
icons/hicolor-icon-theme git=https://gitlab.freedesktop.org/xdg/default-icon-theme.git rev=8d22bbf
|
||||
icons/pop-icon-theme git=https://github.com/pop-os/icon-theme.git rev=1a575a8
|
||||
kde/breeze tar=https://invent.kde.org/plasma/breeze/-/archive/v6.3.4/breeze-v6.3.4.tar.gz blake3=
|
||||
kde/kde-cli-tools tar=https://invent.kde.org/plasma/kde-cli-tools/-/archive/v6.3.4/kde-cli-tools-v6.3.4.tar.gz blake3=
|
||||
kde/kdecoration tar=https://invent.kde.org/plasma/kdecoration/-/archive/v6.3.4/kdecoration-v6.3.4.tar.gz blake3=
|
||||
kde/kf6-attica tar=https://invent.kde.org/frameworks/attica/-/archive/v6.10.0/attica-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-extra-cmake-modules tar=https://invent.kde.org/frameworks/extra-cmake-modules/-/archive/v6.10.0/extra-cmake-modules-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-karchive tar=https://invent.kde.org/frameworks/karchive/-/archive/v6.10.0/karchive-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kauth tar=https://invent.kde.org/frameworks/kauth/-/archive/v6.10.0/kauth-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kbookmarks tar=https://invent.kde.org/frameworks/kbookmarks/-/archive/v6.10.0/kbookmarks-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kcmutils tar=https://invent.kde.org/frameworks/kcmutils/-/archive/v6.10.0/kcmutils-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kcodecs tar=https://invent.kde.org/frameworks/kcodecs/-/archive/v6.10.0/kcodecs-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kcolorscheme tar=https://invent.kde.org/frameworks/kcolorscheme/-/archive/v6.10.0/kcolorscheme-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kcompletion tar=https://invent.kde.org/frameworks/kcompletion/-/archive/v6.10.0/kcompletion-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kconfig tar=https://invent.kde.org/frameworks/kconfig/-/archive/v6.10.0/kconfig-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kconfigwidgets tar=https://invent.kde.org/frameworks/kconfigwidgets/-/archive/v6.10.0/kconfigwidgets-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kcoreaddons tar=https://invent.kde.org/frameworks/kcoreaddons/-/archive/v6.10.0/kcoreaddons-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kcrash tar=https://invent.kde.org/frameworks/kcrash/-/archive/v6.10.0/kcrash-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kdbusaddons tar=https://invent.kde.org/frameworks/kdbusaddons/-/archive/v6.10.0/kdbusaddons-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kdeclarative tar=https://invent.kde.org/frameworks/kdeclarative/-/archive/v6.10.0/kdeclarative-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kded6 tar=https://invent.kde.org/frameworks/kded/-/archive/v6.10.0/kded-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kglobalaccel tar=https://invent.kde.org/frameworks/kglobalaccel/-/archive/v6.10.0/kglobalaccel-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kguiaddons tar=https://invent.kde.org/frameworks/kguiaddons/-/archive/v6.10.0/kguiaddons-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-ki18n tar=https://invent.kde.org/frameworks/ki18n/-/archive/v6.10.0/ki18n-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kiconthemes tar=https://invent.kde.org/frameworks/kiconthemes/-/archive/v6.10.0/kiconthemes-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kidletime tar=https://invent.kde.org/frameworks/kidletime/-/archive/v6.10.0/kidletime-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kio tar=https://invent.kde.org/frameworks/kio/-/archive/v6.10.0/kio-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kirigami tar=https://invent.kde.org/frameworks/kirigami/-/archive/v6.10.0/kirigami-v6.10.0.tar.gz blake3=d0964890aa6523f7067510bb7e6c784ba77611952d952bfdd6422a58a23664f6
|
||||
kde/kf6-kitemmodels tar=https://invent.kde.org/frameworks/kitemmodels/-/archive/v6.10.0/kitemmodels-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kitemviews tar=https://invent.kde.org/frameworks/kitemviews/-/archive/v6.10.0/kitemviews-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kjobwidgets tar=https://invent.kde.org/frameworks/kjobwidgets/-/archive/v6.10.0/kjobwidgets-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-knotifications tar=https://invent.kde.org/frameworks/knotifications/-/archive/v6.10.0/knotifications-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kpackage tar=https://invent.kde.org/frameworks/kpackage/-/archive/v6.10.0/kpackage-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kservice tar=https://invent.kde.org/frameworks/kservice/-/archive/v6.10.0/kservice-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-ktextwidgets tar=https://invent.kde.org/frameworks/ktextwidgets/-/archive/v6.10.0/ktextwidgets-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kwallet tar=https://invent.kde.org/frameworks/kwallet/-/archive/v6.10.0/kwallet-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kwayland tar=https://download.kde.org/stable/plasma/6.3.4/kwayland-6.3.4.tar.xz blake3=
|
||||
kde/kf6-kwidgetsaddons tar=https://invent.kde.org/frameworks/kwidgetsaddons/-/archive/v6.10.0/kwidgetsaddons-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kwindowsystem tar=https://invent.kde.org/frameworks/kwindowsystem/-/archive/v6.10.0/kwindowsystem-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-kxmlgui tar=https://invent.kde.org/frameworks/kxmlgui/-/archive/v6.10.0/kxmlgui-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-prison tar=https://invent.kde.org/frameworks/prison/-/archive/v6.10.0/prison-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-pty tar=https://invent.kde.org/frameworks/kpty/-/archive/v6.10.0/kpty-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-solid tar=https://invent.kde.org/frameworks/solid/-/archive/v6.10.0/solid-v6.10.0.tar.gz blake3=
|
||||
kde/kf6-sonnet tar=https://invent.kde.org/frameworks/sonnet/-/archive/v6.10.0/sonnet-v6.10.0.tar.gz blake3=
|
||||
kde/kglobalacceld tar=https://invent.kde.org/plasma/kglobalacceld/-/archive/v6.0.0/kglobalacceld-v6.0.0.tar.gz blake3=
|
||||
kde/kirigami tar=https://invent.kde.org/frameworks/kirigami/-/archive/v6.10.0/kirigami-v6.10.0.tar.gz blake3=d0964890aa6523f7067510bb7e6c784ba77611952d952bfdd6422a58a23664f6
|
||||
kde/konsole tar=https://invent.kde.org/utilities/konsole/-/archive/v24.08.3/konsole-v24.08.3.tar.gz blake3=
|
||||
kde/kwin tar=https://invent.kde.org/plasma/kwin/-/archive/v6.3.4/kwin-v6.3.4.tar.gz blake3=2aa1e234a75b0aa94f0da3a74d93e2a8e49b30a3afb12dc24b2ecd3abaa94e7f
|
||||
kde/plasma-desktop tar=https://invent.kde.org/plasma/plasma-desktop/-/archive/v6.3.4/plasma-desktop-v6.3.4.tar.gz blake3=
|
||||
kde/plasma-framework tar=https://invent.kde.org/frameworks/plasma-framework/-/archive/v6.10.0/plasma-framework-v6.10.0.tar.gz blake3=
|
||||
kde/plasma-wayland-protocols tar=https://invent.kde.org/libraries/plasma-wayland-protocols/-/archive/v1.16.0/plasma-wayland-protocols-v1.16.0.tar.gz blake3=
|
||||
kde/plasma-workspace tar=https://invent.kde.org/plasma/plasma-workspace/-/archive/v6.3.4/plasma-workspace-v6.3.4.tar.gz blake3=
|
||||
libs/atk tar=https://download.gnome.org/sources/atk/2.38/atk-2.38.0.tar.xz blake3=cbc1b7ba03009ee5cc0e646d8a86117e0d65bf8d105f2e8714fbde0299a8012e
|
||||
libs/cairo tar=https://www.cairographics.org/releases/cairo-1.18.4.tar.xz blake3=b9fa14e02f85ec4e72396c62236c98502d04dbbdf8daf01ab9557a1c7aa7106e
|
||||
libs/duktape tar=https://duktape.org/duktape-2.7.0.tar.xz blake3=b0a17da888847bc9c73624ae3ba7f858ec327a9bbce9d287aee6a2489e518448
|
||||
libs/expat tar=https://github.com/libexpat/libexpat/releases/download/R_2_5_0/expat-2.5.0.tar.xz blake3=ea89dd9a5a2e48d5e44fed38554b36a8f2e365a5091a99d08e30bfb1c15dda5e
|
||||
libs/ffmpeg6 tar=https://ffmpeg.org/releases/ffmpeg-6.0.tar.xz blake3=4879074c357102f85932673044c57c144b0c188ae58edec2a115965536ee340f
|
||||
libs/freetype2 tar=https://sourceforge.net/projects/freetype/files/freetype2/2.13.3/freetype-2.13.3.tar.xz/download blake3=07a01894ccdb584943ce817b57341a8595ce9a92bfaa77c602ec4757dfabd5e2
|
||||
libs/fribidi tar=https://github.com/fribidi/fribidi/releases/download/v1.0.16/fribidi-1.0.16.tar.xz blake3=c16ee250f73f149d7d52dc7d285eb73ac755bad7907d237391e23f429b2b71d5
|
||||
libs/glib tar=https://download.gnome.org/sources/glib/2.87/glib-2.87.0.tar.xz blake3=26b77ae24bc02f85d1c6742fe601167b056085f117cda70da7b805cefa6195e9
|
||||
libs/gstreamer tar=https://gitlab.freedesktop.org/gstreamer/gstreamer/-/archive/1.24.12/gstreamer-1.24.12.tar.gz blake3=181daf73050f7472ec656e7461b7f67028d6002c1133870576033a32e43a364f
|
||||
libs/harfbuzz tar=https://github.com/harfbuzz/harfbuzz/releases/download/11.0.1/harfbuzz-11.0.1.tar.xz blake3=51f0edaaf2e9b7a7176d3252f15d03d409ef7ad35f77b050c407de89f85b77c5
|
||||
libs/jansson tar=https://github.com/akheron/jansson/releases/download/v2.10/jansson-2.10.tar.gz blake3=3c74f374a6c7ac5e323f72d87e49e5309ca922ca26cfe4992873b31f28776624
|
||||
libs/lcms2-stub path=source
|
||||
libs/libarchive tar=https://libarchive.org/downloads/libarchive-3.6.2.tar.xz blake3=f98695fe81235a74fa3fc2c3ba0f0d4f13ea15f9be3850b83e304cf5d78be710
|
||||
libs/libatomic same_as=../../dev/gcc13
|
||||
libs/libcosmic git=https://gitlab.redox-os.org/redox-os/libcosmic.git rev=
|
||||
libs/libdisplay-info-stub path=source
|
||||
libs/libepoxy-stub path=source
|
||||
libs/libffi tar=https://github.com/libffi/libffi/releases/download/v3.4.5/libffi-3.4.5.tar.gz blake3=f9a2cfe1d2ac8d211c18c99f9cfafe5537925101bfb92c2d44d844680dd82264
|
||||
libs/libflac tar=https://github.com/xiph/flac/releases/download/1.5.0/flac-1.5.0.tar.xz blake3=2adca3cd8da4b577ebb9c12e73c91cf6f6a7feb7485b3f003853b82710bada84
|
||||
libs/libgmp tar=https://ftp.gnu.org/gnu/gmp/gmp-6.3.0.tar.xz blake3=fffe4996713928ae19331c8ef39129e46d3bf5b7182820656fd4639435cd83a4
|
||||
libs/libiconv tar=https://ftp.gnu.org/gnu/libiconv/libiconv-1.17.tar.gz blake3=820b3b9fd3e2181bfb95475f01e9a3451e6d751e4f8c98ebcdcca1d8aa720f7f
|
||||
libs/libjpeg tar=https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/3.1.0/libjpeg-turbo-3.1.0.tar.gz blake3=3efc14da55c56fc0a6a50f109d9e1ee8a91f5ae7dd17a21d3aebe04a65f3ee96
|
||||
libs/libmodplug1 tar=https://pilotfiber.dl.sourceforge.net/project/modplug-xmms/libmodplug/0.8.9.0/libmodplug-0.8.9.0.tar.gz blake3=01d71f7fe4e1abeb848db02b74c70ab2fd51e824f5ea7e9e18631571a76c3592
|
||||
libs/libmpfr tar=https://www.mpfr.org/mpfr-current/mpfr-4.2.2.tar.xz blake3=11d59d061ef8db588650bc7dc5172594a6e5aad013994801c6f63011a62b191d
|
||||
libs/libnettle tar=https://ftp.gnu.org/gnu/nettle/nettle-3.9.1.tar.gz blake3=e4bfbda32f4fdf5ed96c152efe3a3867193b690faa5378d02a2a6fd052ee3393
|
||||
libs/libogg tar=https://github.com/xiph/ogg/releases/download/v1.3.4/libogg-1.3.4.tar.xz blake3=1cffbe7c498555ddfdb1390d7a38179c4bead6129ea37b1b1d54f3a76b816304
|
||||
libs/libopus tar=https://downloads.xiph.org/releases/opus/opus-1.6.1.tar.gz blake3=874bd7d28e24f10d88105c7d846a2e5bf085284af91a0ee36b05674a8f78e759
|
||||
libs/liborbital git=https://gitlab.redox-os.org/redox-os/liborbital.git rev=cdb08e8
|
||||
libs/libpng tar=https://github.com/pnggroup/libpng/archive/refs/tags/v1.6.46.tar.gz blake3=36f4bbb48c70975116b00ab0cff577931b96f703b2774ac3b33131d001419435
|
||||
libs/libpsl tar=https://github.com/rockdaboot/libpsl/releases/download/0.21.5/libpsl-0.21.5.tar.lz blake3=91318b7b876b12ff4649b7a0d6f6ed4ab1ab44f48a49508c8978ab7b4ccf3298
|
||||
libs/libqrencode tar=https://github.com/fukuchi/libqrencode/archive/refs/tags/v4.1.1.tar.gz blake3=78bf8bbcfb037140d0e98dc355e77416c9c9b0fd3ac12fd6e767b07d68f60f8c
|
||||
libs/libsodium tar=https://github.com/jedisct1/libsodium/archive/1.0.16.tar.gz blake3=2482633f872c173f9a42e6badb44c3efb042e783e664fdf8b1046babfa2405e7
|
||||
libs/libssh2 tar=https://www.libssh2.org/download/libssh2-1.10.0.tar.gz blake3=2447216ce82c1d22301456bb02f60dfb6688f1461417b90f900c099a87f1292f
|
||||
libs/libstdcxx-v3 same_as=../../dev/gcc13
|
||||
libs/libudev-stub path=source
|
||||
libs/liburcu tar=https://lttng.org/files/urcu/userspace-rcu-0.14.0.tar.bz2 blake3=
|
||||
libs/libuv tar=https://dist.libuv.org/dist/v1.51.0/libuv-v1.51.0.tar.gz blake3=e8b5e68bc2d0776ac4ea67df59d694fca58d5cc570c103443a2284e723d01fc2
|
||||
libs/libvorbis tar=https://github.com/xiph/vorbis/releases/download/v1.3.7/libvorbis-1.3.7.tar.xz blake3=c67f3f74ec26d93a5571c4404a64eb6e6587d7d77b46b552f7b410f5bc5b1f03
|
||||
libs/libxcvt-stub path=source
|
||||
libs/libxml2 tar=https://download.gnome.org/sources/libxml2/2.11/libxml2-2.11.3.tar.xz blake3=0653d3750576299c4cb88740942165671b576ff93019f3d669b3f37136225ab7
|
||||
libs/lua-compat-53 git=https://github.com/lunarmodules/lua-compat-5.3.git rev=
|
||||
libs/luv git=https://github.com/luvit/luv.git rev=
|
||||
libs/mesa git=https://gitlab.redox-os.org/redox-os/mesa.git rev=0ecd6b66c
|
||||
libs/mesa-glu tar=https://archive.mesa3d.org/glu/glu-9.0.3.tar.xz blake3=beed1665ed983540e7502289ec50c7e66d840820af3e9ef21c9c4a7e9686ab9f
|
||||
libs/mpc tar=https://ftp.gnu.org/gnu/mpc/mpc-1.3.1.tar.gz blake3=
|
||||
libs/ncurses tar=https://ftp.gnu.org/gnu/ncurses/ncurses-6.6.tar.gz blake3=fbec55697a01f99b9cc3f25be55e73ae7091f4c53e5d81a1ea15734c4e5b7238
|
||||
libs/ncursesw same_as=../ncurses
|
||||
libs/nghttp2 tar=https://github.com/nghttp2/nghttp2/releases/download/v1.64.0/nghttp2-1.64.0.tar.xz blake3=1bbc08de4816769d800c42f501a00c1ba3f5efa1b76e1f65d2e5bdf3aa30354d
|
||||
libs/openssl1 git=https://gitlab.redox-os.org/redox-os/openssl.git rev=
|
||||
libs/opusfile tar=https://downloads.xiph.org/releases/opus/opusfile-0.12.tar.gz blake3=1b6a5c371a0ea2ae8e37ab2e921388dfef9252dbf7f60045192dabbdd898f2bf
|
||||
libs/pango tar=https://download.gnome.org/sources/pango/1.56/pango-1.56.3.tar.xz blake3=78542feaaf007c1d648b94c4e9b6655ed7515d27ce434766aea99bef886c21ac
|
||||
libs/pcre tar=https://mirrors.gigenet.com/OSDN//sfnet/p/pc/pcre/pcre/8.42/pcre-8.42.tar.gz blake3=12d515ba12a816994def6b1e7196b5783fd2cfe495733a9167fa4d71dbe10248
|
||||
libs/pcre2 tar=https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.45/pcre2-10.45.tar.bz2 blake3=aea544846f9a03c1ec62c9f8d1c9a4187cc3cce557e53e6876eb6a58c7cdd9fe
|
||||
libs/pixman tar=https://www.cairographics.org/releases/pixman-0.46.0.tar.xz blake3=379369245a0bbd13784bf550c87622964a6aba87edf598ffa137dc10201746e0
|
||||
libs/readline tar=https://ftp.gnu.org/gnu/readline/readline-8.3.tar.gz blake3=7109f094062bda387a0c16b4875375b96e36437bebbbd8d8f91bb27ba01d687f
|
||||
libs/redox-fatfs git=https://gitlab.redox-os.org/redox-os/redox-fatfs.git rev=
|
||||
libs/sdl-gfx tar=https://sourceforge.net/projects/sdlgfx/files/SDL_gfx-2.0.25.tar.gz blake3=e6f571a38e51d369b010f4b10eb35b95e3d2edae2edd796241c47ea8376581e6
|
||||
libs/sdl1 git=https://gitlab.redox-os.org/redox-os/sdl1.2.git rev=
|
||||
libs/sdl1-image tar=https://www.libsdl.org/projects/SDL_image/release/SDL_image-1.2.12.tar.gz blake3=731a6f8cad9fff22c82394bd1c0c34ce4aa60fa8923f3755a3e3239f1e269389
|
||||
libs/sdl1-mixer tar=https://www.libsdl.org/projects/SDL_mixer/release/SDL_mixer-1.2.12.tar.gz blake3=ef23bab2d42250dfdc51ce6939ee7b393973ff11a0dd3481f32180b489d2661c
|
||||
libs/sdl1-ttf tar=https://www.libsdl.org/projects/SDL_ttf/release/SDL_ttf-2.0.11.tar.gz blake3=a684e57553e43b55ab28b064d1d5d44b8749299f259da31a62d671fc1d5505ee
|
||||
libs/sdl2 git=https://gitlab.redox-os.org/redox-os/sdl2.git rev=
|
||||
libs/sdl2-gfx tar=http://www.ferzkopp.net/Software/SDL2_gfx/SDL2_gfx-1.0.4.tar.gz blake3=2e9bd2dc0f004349b51418f33219ebf5cd69f25ed0ba660373652a662cbb857c
|
||||
libs/sdl2-image tar=https://www.libsdl.org/projects/SDL_image/release/SDL2_image-2.0.4.tar.gz blake3=
|
||||
libs/sdl2-mixer tar=https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-2.8.1.tar.gz blake3=fa0798ce7ffdb5f89545311292374e5b7af479df8bc99a4aacfb40d2ab2f8384
|
||||
libs/sdl2-ttf tar=https://www.libsdl.org/projects/SDL_ttf/release/SDL2_ttf-2.0.15.tar.gz blake3=9814a07f33a3501b414f0fc7fa962e7d7ffc56748406f3798b7698b8d7e7fe12
|
||||
libs/termcap tar=https://ftp.gnu.org/gnu/termcap/termcap-1.3.1.tar.gz blake3=57c095e0bb6e60e7b4a0597f51f7ac15b501ca0f95d37424d8d13978d28b8da3
|
||||
libs/unibilium tar=https://github.com/neovim/unibilium/archive/refs/tags/v2.1.2.tar.gz blake3=856a7593a412942f4716bb55bfdd225f3ce92cb013b9d4a44693255f0570b1c7
|
||||
libs/utf8proc tar=https://github.com/JuliaStrings/utf8proc/archive/refs/tags/v2.10.0.tar.gz blake3=6f675db5d1ae55ad0825351ba9c58a5b5c24c862f559cc7bfed1cb63c1185594
|
||||
libs/zbus path=source
|
||||
libs/zlib tar=https://www.zlib.net/fossils/zlib-1.3.tar.gz blake3=ec1abc6f672a7a6ee6f49ba544cc9529f73121b478310473be44fee22a140ebf
|
||||
math/orbcalculator git=https://gitlab.redox-os.org/redox-os/orbcalculator.git rev=
|
||||
net/nginx tar=https://nginx.org/download/nginx-1.28.0.tar.gz blake3=
|
||||
net/openssh tar=https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-9.8p1.tar.gz blake3=
|
||||
net/redox-ssh git=https://gitlab.redox-os.org/redox-os/redox-ssh.git rev=
|
||||
net/rsync tar=https://download.samba.org/pub/rsync/src/rsync-3.4.1.tar.gz blake3=
|
||||
other/ca-certificates git=https://gitlab.redox-os.org/redox-os/ca-certificates.git rev=8139d99
|
||||
other/cookbook git=https://gitlab.redox-os.org/redox-os/redox.git rev=
|
||||
other/generaluser-gs git=https://gitlab.redox-os.org/redox-os/generaluser-gs.git rev=
|
||||
other/jeremy git=https://gitlab.redox-os.org/jackpot51/jeremy.git rev=
|
||||
other/rustconf2025 git=https://github.com/jackpot51/rustconf2025.git rev=
|
||||
other/shared-mime-info tar=https://gitlab.freedesktop.org/xdg/shared-mime-info/-/archive/2.4/shared-mime-info-2.4.tar.gz blake3=ad130f2f923ab3d5455c643e6257abf3598339fdd134ad0fac4e5dbbbf070eb9
|
||||
other/terminfo git=https://github.com/sajattack/terminfo rev=dc5712b
|
||||
qt/qt6-sensors tar=https://download.qt.io/official_releases/qt/6.11/6.11.0/submodules/qtsensors-everywhere-src-6.11.0.tar.xz blake3=
|
||||
shells/bash tar=https://ftp.gnu.org/gnu/bash/bash-5.2.15.tar.gz blake3=c1548e3f2a9b6de5296e18c28b3d2007985e647273e03f039efd3e489edaa41f
|
||||
shells/nushell git=https://github.com/nushell/nushell rev=172a070a4bbeff15a289813bc73d4628a3032210
|
||||
shells/zsh tar=https://github.com/zsh-users/zsh/archive/refs/tags/zsh-5.9.tar.gz blake3=a15b94fae03e87aba6fc6a27df3c98e610b85b0c7c0fc90248f07fdcb8816860
|
||||
sound/freepats git=https://gitlab.redox-os.org/redox-os/freepats.git rev=
|
||||
sound/rodioplay git=https://gitlab.redox-os.org/redox-os/rodioplay.git rev=
|
||||
sound/timidity git=https://gitlab.redox-os.org/redox-os/timidity.git rev=
|
||||
system/cpufreqd path=source
|
||||
system/cub path=source
|
||||
system/driver-manager path=source
|
||||
system/driver-params path=source
|
||||
system/evdevd path=source
|
||||
system/firmware-loader path=source
|
||||
system/hwrngd path=source
|
||||
system/iommu path=source
|
||||
system/numad path=source
|
||||
system/redbear-acmd path=source
|
||||
system/redbear-authd path=source
|
||||
system/redbear-btctl path=source
|
||||
system/redbear-dbus-services path=files
|
||||
system/redbear-ecmd path=source
|
||||
system/redbear-firmware path=source
|
||||
system/redbear-greeter path=source
|
||||
system/redbear-hwutils path=source
|
||||
system/redbear-info path=source
|
||||
system/redbear-login-protocol path=source
|
||||
system/redbear-meta path=source
|
||||
system/redbear-mtr path=source
|
||||
system/redbear-netctl path=source
|
||||
system/redbear-netctl-console path=source
|
||||
system/redbear-netstat path=source
|
||||
system/redbear-nmap path=source
|
||||
system/redbear-notifications path=source
|
||||
system/redbear-polkit path=source
|
||||
system/redbear-quirks path=source
|
||||
system/redbear-session-launch path=source
|
||||
system/redbear-sessiond path=source
|
||||
system/redbear-traceroute path=source
|
||||
system/redbear-udisks path=source
|
||||
system/redbear-upower path=source
|
||||
system/redbear-usbaudiod path=source
|
||||
system/redbear-wifictl path=source
|
||||
system/thermald path=source
|
||||
system/udev-shim path=source
|
||||
terminal/bash-completion tar=https://github.com/scop/bash-completion/releases/download/2.17.0/bash-completion-2.17.0.tar.xz blake3=
|
||||
terminal/pls git=https://github.com/pls-rs/pls rev=
|
||||
terminal/zoxide git=https://github.com/ajeetdsouza/zoxide rev=
|
||||
tests/acid git=https://gitlab.redox-os.org/redox-os/acid.git rev=
|
||||
tests/acid-bins same_as=../acid
|
||||
tests/benchmarks git=https://gitlab.redox-os.org/redox-os/benchmarks rev=
|
||||
tests/iperf3 tar=https://downloads.es.net/pub/iperf/iperf-3.20.tar.gz blake3=
|
||||
tests/openposixtestsuite git=https://gitlab.redox-os.org/redox-os/openposixtestsuite.git rev=
|
||||
tests/os-test git=https://gitlab.com/sortix/os-test rev=
|
||||
tests/os-test-bins same_as=../os-test
|
||||
tests/os-test-result same_as=../os-test
|
||||
tests/redox-drm-prime-test path=source
|
||||
tests/redox-posix-tests git=https://gitlab.redox-os.org/redox-os/redox-posix-tests.git rev=
|
||||
tests/relibc-phase1-tests path=source
|
||||
tests/relibc-tests same_as=../../core/relibc
|
||||
tests/relibc-tests-bins same_as=../../core/relibc
|
||||
tests/schedrs git=https://gitlab.redox-os.org/akshitgaur2005/schedrs.git rev=
|
||||
tests/sysbench git=https://github.com/akopytov/sysbench.git rev=
|
||||
tests/vttest tar=https://invisible-island.net/archives/vttest/vttest-20140305.tgz blake3=b515b9a5e1f1498ed99e1a1c172fbcfdf2b7a214e185bd2005cc994407ded89e
|
||||
tools/bzip2 tar=https://sourceware.org/pub/bzip2/bzip2-1.0.8.tar.gz blake3=97af3f520629c65fe41292f77e6ca798fe594d7987bfb2aebe7c6fcdc7ab5ed2
|
||||
tools/cleye git=https://gitlab.redox-os.org/redox-os/cleye.git rev=
|
||||
tools/cosmic-edit git=https://github.com/pop-os/cosmic-edit.git rev=epoch-1.0.8
|
||||
tools/cosmic-files git=https://github.com/pop-os/cosmic-files.git rev=epoch-1.0.8
|
||||
tools/cosmic-reader git=https://github.com/pop-os/cosmic-reader.git rev=epoch-1.0.8
|
||||
tools/cosmic-settings git=https://github.com/pop-os/cosmic-settings.git rev=
|
||||
tools/cosmic-store git=https://github.com/pop-os/cosmic-store.git rev=epoch-1.0.8
|
||||
tools/cosmic-term git=https://github.com/pop-os/cosmic-term.git rev=epoch-1.0.8
|
||||
tools/cosmic-text git=https://github.com/pop-os/cosmic-text.git rev=
|
||||
tools/diffutils tar=https://ftp.gnu.org/gnu/diffutils/diffutils-3.6.tar.xz blake3=086a95093c15edcdb826e75ff4de6c2213de6fbd2eb13538d07bdc3286dfb4a4
|
||||
tools/fd git=https://github.com/sharkdp/fd.git rev=840a565d3aadbeb303b10a01c0aa3561924dfc46
|
||||
tools/file tar=https://astron.com/pub/file/file-5.46.tar.gz blake3=
|
||||
tools/friar git=https://github.com/jackpot51/friar.git rev=
|
||||
tools/gettext tar=https://ftp.gnu.org/gnu/gettext/gettext-0.22.5.tar.gz blake3=cb3f3a34da7ce1a92746df81f5b78c5d53841973a24eb80ab76537263d380ec0
|
||||
tools/gnu-binutils tar=https://ftp.gnu.org/gnu/binutils/binutils-2.43.1.tar.xz blake3=f074c81313b70eabc58ce9a9411cd771c5fa2433792d0ad8abcc45f603f58ed6
|
||||
tools/gnu-grep tar=https://ftp.gnu.org/gnu/grep/grep-3.1.tar.xz blake3=46b6e24dfa1b0f309f4eae3c450d612396c8faa6510b53a55f629e4f4c70b4a3
|
||||
tools/helix git=https://github.com/greyshaman/helix.git rev=
|
||||
tools/libc-bench tar=https://www.etalabs.net/releases/libc-bench-20110206.tar.gz blake3=64093102f29faa76da455f55a7b4be25b6d74d5c3d6fe88dbbc38aaae185182f
|
||||
tools/lsd git=https://github.com/lsd-rs/lsd rev=
|
||||
tools/nano tar=https://www.nano-editor.org/dist/v7/nano-7.2.tar.xz blake3=
|
||||
tools/onefetch git=https://github.com/o2sh/onefetch rev=
|
||||
tools/patchelf tar=https://github.com/NixOS/patchelf/releases/download/0.18.0/patchelf-0.18.0.tar.bz2 blake3=f843b32bdf3ee8a1f465e92d3fef34f30c48ccef9c112fdb793e2e7f2ae7283a
|
||||
tools/pathfinder git=https://gitlab.redox-os.org/redox-os/pathfinder.git rev=
|
||||
tools/perg git=https://github.com/guerinoni/perg.git rev=e206fab6bbd9c363c686fa7503d318304e48ddbe
|
||||
tools/periodictable git=https://gitlab.redox-os.org/redox-os/periodictable.git rev=
|
||||
tools/powerline git=https://github.com/jD91mZM2/powerline-rs rev=
|
||||
tools/ripgrep git=https://github.com/jackpot51/ripgrep.git rev=
|
||||
tools/schismtracker tar=https://github.com/schismtracker/schismtracker/archive/20181223.tar.gz blake3=057e973f4f84cf898e2240d67c0e92f25086d8b9ffdc7e0c7ef81dd8dc81bc70
|
||||
tools/sed tar=https://ftp.gnu.org/gnu/sed/sed-4.4.tar.xz blake3=a88c12b2b4304e53e3c7ae2eb0499d02e28873c1b9e1a6871e5347c6886a1ecd
|
||||
tools/shellharden git=https://github.com/anordal/shellharden.git rev=bd24c99d5d1e76452b6d0749404837c1c95d923c
|
||||
tools/shellstorm git=https://gitlab.redox-os.org/redox-os/shellstorm.git rev=
|
||||
tools/smith git=https://gitlab.redox-os.org/redox-os/Smith.git rev=
|
||||
tools/sodium git=https://gitlab.redox-os.org/redox-os/sodium.git rev=
|
||||
tools/tokei git=https://github.com/XAMPPRocky/tokei.git rev=
|
||||
tools/twin-commander git=https://github.com/kivimango/twin-commander.git rev=
|
||||
tools/vim tar=https://github.com/vim/vim/archive/refs/tags/v9.1.0821.tar.gz blake3=d1f5802ceb047b09143f1764bf4016f084cf7e6c026c7047919264c9f262a5dd
|
||||
tools/xz tar=https://github.com/tukaani-project/xz/releases/download/v5.2.13/xz-5.2.13.tar.gz blake3=edc6350542e8cb7188a878135e5b9bd592d687e5b47451ca1c89d51cc4bc6b53
|
||||
tui/goaccess tar=https://tar.goaccess.io/goaccess-1.9.4.tar.gz blake3=a7a7641c98956e8941191956129141e071321851d004269c7d21bce536d9224a
|
||||
tui/mc tar=https://ftp.osuosl.org/pub/midnightcommander/mc-4.8.33.tar.xz blake3=cad9c1587f2976b9e42016191a72c4f23a07222c96ec7a9454a1a66ce639ac63
|
||||
tui/mdp git=https://github.com/visit1985/mdp.git rev=
|
||||
tui/ncdu tar=https://dev.yorhel.nl/download/ncdu-1.22.tar.gz blake3=b7838c03ded7207a328a26c840ec3d62d3be6bbf7269a70ea3430c6cbf065960
|
||||
video/sdl-player git=https://gitlab.redox-os.org/redox-os/sdl-player.git rev=
|
||||
wayland/qt6-wayland-smoke path=source
|
||||
wayland/redbear-compositor path=source
|
||||
wayland/seatd-redox tar=https://git.sr.ht/~kennylevinsen/seatd/archive/0.9.1.tar.gz blake3=
|
||||
wayland/smallvil git=https://github.com/jackpot51/smithay rev=
|
||||
web/netsurf tar=https://download.netsurf-browser.org/netsurf/releases/source-full/netsurf-all-3.11.tar.gz blake3=cd406668a9ed5712efac1a8685125b83626690b73bbc6cb5de82ef00e3f65087
|
||||
web/website git=https://gitlab.redox-os.org/redox-os/website rev=
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,913 @@
|
||||
diff --git a/src/context/file.rs b/src/context/file.rs
|
||||
index 2d3790f..150f483 100644
|
||||
--- a/src/context/file.rs
|
||||
+++ b/src/context/file.rs
|
||||
@@ -4,7 +4,7 @@ use crate::{
|
||||
event,
|
||||
scheme::{self, SchemeId},
|
||||
sync::{CleanLockToken, RwLock, L6},
|
||||
- syscall::error::Result,
|
||||
+ syscall::error::{Error, Result, ESTALE},
|
||||
};
|
||||
use alloc::sync::Arc;
|
||||
use syscall::{schemev2::NewFdFlags, RwFlags, O_APPEND, O_NONBLOCK};
|
||||
@@ -18,6 +18,7 @@ pub struct FileDescription {
|
||||
pub offset: u64,
|
||||
/// The scheme that this file refers to
|
||||
pub scheme: SchemeId,
|
||||
+ pub scheme_generation: Option<u64>,
|
||||
/// The number the scheme uses to refer to this file
|
||||
pub number: usize,
|
||||
/// The flags passed to open or fcntl(SETFL)
|
||||
@@ -32,6 +33,52 @@ bitflags! {
|
||||
}
|
||||
}
|
||||
impl FileDescription {
|
||||
+ pub fn with_generation(
|
||||
+ scheme: SchemeId,
|
||||
+ scheme_generation: Option<u64>,
|
||||
+ number: usize,
|
||||
+ offset: u64,
|
||||
+ flags: u32,
|
||||
+ internal_flags: InternalFlags,
|
||||
+ ) -> Self {
|
||||
+ Self {
|
||||
+ offset,
|
||||
+ scheme,
|
||||
+ scheme_generation,
|
||||
+ number,
|
||||
+ flags,
|
||||
+ internal_flags,
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ pub fn new(
|
||||
+ scheme: SchemeId,
|
||||
+ number: usize,
|
||||
+ offset: u64,
|
||||
+ flags: u32,
|
||||
+ internal_flags: InternalFlags,
|
||||
+ token: &mut CleanLockToken,
|
||||
+ ) -> Self {
|
||||
+ Self::with_generation(
|
||||
+ scheme,
|
||||
+ Some(scheme::current_scheme_generation(token.token(), scheme)),
|
||||
+ number,
|
||||
+ offset,
|
||||
+ flags,
|
||||
+ internal_flags,
|
||||
+ )
|
||||
+ }
|
||||
+
|
||||
+ pub fn get_scheme(&self, token: &mut CleanLockToken) -> Result<scheme::KernelSchemes> {
|
||||
+ if let Some(expected_generation) = self.scheme_generation
|
||||
+ && expected_generation != scheme::current_scheme_generation(token.token(), self.scheme)
|
||||
+ {
|
||||
+ return Err(Error::new(ESTALE));
|
||||
+ }
|
||||
+
|
||||
+ scheme::get_scheme(token.token(), self.scheme)
|
||||
+ }
|
||||
+
|
||||
pub fn rw_flags(&self, rw: RwFlags) -> u32 {
|
||||
let mut ret = self.flags & !(O_NONBLOCK | O_APPEND) as u32;
|
||||
if rw.contains(RwFlags::APPEND) {
|
||||
@@ -76,7 +123,7 @@ impl FileDescription {
|
||||
pub fn try_close(self, token: &mut CleanLockToken) -> Result<()> {
|
||||
event::unregister_file(self.scheme, self.number, token);
|
||||
|
||||
- let scheme = scheme::get_scheme(token.token(), self.scheme)?;
|
||||
+ let scheme = self.get_scheme(token)?;
|
||||
|
||||
scheme.close(self.number, token)
|
||||
}
|
||||
@@ -85,12 +132,12 @@ impl FileDescription {
|
||||
impl FileDescriptor {
|
||||
pub fn close(self, token: &mut CleanLockToken) -> Result<()> {
|
||||
{
|
||||
- let (scheme_id, number, internal_flags) = {
|
||||
+ let (desc, number, internal_flags) = {
|
||||
let desc = self.description.read(token.token());
|
||||
- (desc.scheme, desc.number, desc.internal_flags)
|
||||
+ (*desc, desc.number, desc.internal_flags)
|
||||
};
|
||||
if internal_flags.contains(InternalFlags::NOTIFY_ON_NEXT_DETACH) {
|
||||
- let scheme = scheme::get_scheme(token.token(), scheme_id)?;
|
||||
+ let scheme = desc.get_scheme(token)?;
|
||||
scheme.detach(number, token)?;
|
||||
}
|
||||
}
|
||||
diff --git a/src/context/memory.rs b/src/context/memory.rs
|
||||
index 93446ba..a862b35 100644
|
||||
--- a/src/context/memory.rs
|
||||
+++ b/src/context/memory.rs
|
||||
@@ -64,14 +64,13 @@ impl UnmapResult {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
- let (scheme_id, number) = {
|
||||
- let desc = description.write(token.token());
|
||||
- (desc.scheme, desc.number)
|
||||
+ let (scheme, number) = {
|
||||
+ let desc = *description.read(token.token());
|
||||
+ (desc.get_scheme(token)?, desc.number)
|
||||
};
|
||||
|
||||
- let scheme_opt = scheme::get_scheme(token.token(), scheme_id);
|
||||
- let funmap_result = scheme_opt
|
||||
- .and_then(|scheme| scheme.kfunmap(number, base_offset, self.size, self.flags, token));
|
||||
+ let funmap_result = scheme
|
||||
+ .kfunmap(number, base_offset, self.size, self.flags, token);
|
||||
|
||||
if let Ok(fd) = Arc::try_unwrap(description) {
|
||||
fd.into_inner().try_close(token)?;
|
||||
@@ -2687,20 +2686,13 @@ fn correct_inner<'l>(
|
||||
// XXX: This is cheating, but guaranteed we won't deadlock because we've dropped addr_space_guard
|
||||
let mut token = unsafe { CleanLockToken::new() };
|
||||
|
||||
- let (scheme_id, scheme_number) = {
|
||||
- let desc = &file_ref.description.read(token.token());
|
||||
- (desc.scheme, desc.number)
|
||||
+ let desc = *file_ref.description.read(token.token());
|
||||
+ let scheme = desc.get_scheme(&mut token).map_err(|_| PfError::Segv)?;
|
||||
+ let scheme_number = desc.number;
|
||||
+ let user_inner = match scheme {
|
||||
+ KernelSchemes::User(user) => user.inner,
|
||||
+ _ => return Err(PfError::Segv),
|
||||
};
|
||||
- let user_inner = scheme::get_scheme(token.token(), scheme_id)
|
||||
- .ok()
|
||||
- .and_then(|s| {
|
||||
- if let KernelSchemes::User(user) = s {
|
||||
- Some(user.inner)
|
||||
- } else {
|
||||
- None
|
||||
- }
|
||||
- })
|
||||
- .ok_or(PfError::Segv)?;
|
||||
|
||||
let offset = file_ref.base_offset as u64 + (pages_from_grant_start * PAGE_SIZE) as u64;
|
||||
user_inner
|
||||
diff --git a/src/scheme/mod.rs b/src/scheme/mod.rs
|
||||
index d30272c..765e547 100644
|
||||
--- a/src/scheme/mod.rs
|
||||
+++ b/src/scheme/mod.rs
|
||||
@@ -14,7 +14,7 @@ use alloc::{
|
||||
};
|
||||
use core::{
|
||||
str,
|
||||
- sync::atomic::{AtomicUsize, Ordering},
|
||||
+ sync::atomic::{AtomicU64, AtomicUsize, Ordering},
|
||||
};
|
||||
use hashbrown::hash_map::{self, DefaultHashBuilder, HashMap};
|
||||
use spin::Once;
|
||||
@@ -169,6 +169,7 @@ enum Handle {
|
||||
|
||||
/// Schemes list
|
||||
static HANDLES: Once<RwLock<L1, HashMap<SchemeId, Handle>>> = Once::new();
|
||||
+static SCHEME_GENERATIONS: Once<RwLock<L1, HashMap<SchemeId, AtomicU64>>> = Once::new();
|
||||
static SCHEME_LIST_NEXT_ID: AtomicUsize = AtomicUsize::new(MAX_GLOBAL_SCHEMES);
|
||||
static SCHEME_LIST_ID: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
@@ -204,6 +205,10 @@ fn init_schemes() -> RwLock<L1, HashMap<SchemeId, Handle>> {
|
||||
RwLock::new(handles)
|
||||
}
|
||||
|
||||
+fn init_scheme_generations() -> RwLock<L1, HashMap<SchemeId, AtomicU64>> {
|
||||
+ RwLock::new(HashMap::new())
|
||||
+}
|
||||
+
|
||||
/// Get a handle to a scheme.
|
||||
pub fn get_scheme(token: LockToken<'_, L0>, scheme_id: SchemeId) -> Result<KernelSchemes> {
|
||||
match handles().read(token).get(&scheme_id) {
|
||||
@@ -212,10 +217,33 @@ pub fn get_scheme(token: LockToken<'_, L0>, scheme_id: SchemeId) -> Result<Kerne
|
||||
}
|
||||
}
|
||||
|
||||
+pub fn current_scheme_generation(token: LockToken<'_, L0>, scheme_id: SchemeId) -> u64 {
|
||||
+ scheme_generations()
|
||||
+ .read(token)
|
||||
+ .get(&scheme_id)
|
||||
+ .map(|generation| generation.load(Ordering::Acquire))
|
||||
+ .unwrap_or(0)
|
||||
+}
|
||||
+
|
||||
fn handles<'a>() -> &'a RwLock<L1, HashMap<SchemeId, Handle>> {
|
||||
HANDLES.call_once(init_schemes)
|
||||
}
|
||||
|
||||
+fn scheme_generations<'a>() -> &'a RwLock<L1, HashMap<SchemeId, AtomicU64>> {
|
||||
+ SCHEME_GENERATIONS.call_once(init_scheme_generations)
|
||||
+}
|
||||
+
|
||||
+fn increment_scheme_generation(scheme_id: SchemeId, token: &mut CleanLockToken) {
|
||||
+ match scheme_generations().write(token.token()).entry(scheme_id) {
|
||||
+ hash_map::Entry::Occupied(entry) => {
|
||||
+ entry.get().fetch_add(1, Ordering::AcqRel);
|
||||
+ }
|
||||
+ hash_map::Entry::Vacant(entry) => {
|
||||
+ entry.insert(AtomicU64::new(1));
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/// Scheme list type
|
||||
pub struct SchemeList;
|
||||
|
||||
@@ -260,9 +288,14 @@ impl SchemeList {
|
||||
|
||||
/// Remove a scheme
|
||||
fn remove(&self, id: usize, token: &mut CleanLockToken) {
|
||||
- let scheme = handles().write(token.token()).remove(&SchemeId(id));
|
||||
+ let scheme_id = SchemeId(id);
|
||||
+ let scheme = handles().write(token.token()).remove(&scheme_id);
|
||||
|
||||
assert!(scheme.is_some());
|
||||
+ if let Some(Handle::Scheme(KernelSchemes::User(user))) = scheme.as_ref() {
|
||||
+ user.inner.fail_pending_calls(token);
|
||||
+ }
|
||||
+ increment_scheme_generation(scheme_id, token);
|
||||
if let Some(Handle::Scheme(KernelSchemes::User(user))) = scheme
|
||||
&& let Some(user) = Arc::into_inner(user.inner)
|
||||
{
|
||||
@@ -287,32 +320,32 @@ impl KernelScheme for SchemeList {
|
||||
token: &mut CleanLockToken,
|
||||
) -> Result<OpenResult> {
|
||||
let scheme_id = SchemeId(scheme_id);
|
||||
- match handles()
|
||||
- .read(token.token())
|
||||
- .get(&scheme_id)
|
||||
- .ok_or(Error::new(EBADF))?
|
||||
- {
|
||||
- Handle::Scheme(KernelSchemes::User(UserScheme { inner })) => {
|
||||
- let inner = inner.clone();
|
||||
- assert!(scheme_id == inner.scheme_id);
|
||||
- let scheme = scheme_id;
|
||||
- let params = unsafe { user_buf.read_exact::<NewFdParams>()? };
|
||||
-
|
||||
- return Ok(OpenResult::External(Arc::new(RwLock::new(
|
||||
- FileDescription {
|
||||
- scheme,
|
||||
- number: params.number,
|
||||
- offset: params.offset,
|
||||
- flags: params.flags as u32,
|
||||
- internal_flags: InternalFlags::from_extra0(params.internal_flags)
|
||||
- .ok_or(Error::new(EINVAL))?,
|
||||
- },
|
||||
- ))));
|
||||
+ let maybe_inner = {
|
||||
+ let handles = handles().read(token.token());
|
||||
+ match handles.get(&scheme_id).ok_or(Error::new(EBADF))? {
|
||||
+ Handle::Scheme(KernelSchemes::User(UserScheme { inner })) => Some(inner.clone()),
|
||||
+ Handle::SchemeCreationCapability => None,
|
||||
+ _ => return Err(Error::new(EBADF)),
|
||||
}
|
||||
- Handle::SchemeCreationCapability => (),
|
||||
- _ => return Err(Error::new(EBADF)),
|
||||
};
|
||||
|
||||
+ if let Some(inner) = maybe_inner {
|
||||
+ assert!(scheme_id == inner.scheme_id);
|
||||
+ let params = unsafe { user_buf.read_exact::<NewFdParams>()? };
|
||||
+
|
||||
+ return Ok(OpenResult::External(Arc::new(RwLock::new(
|
||||
+ FileDescription::new(
|
||||
+ scheme_id,
|
||||
+ params.number,
|
||||
+ params.offset,
|
||||
+ params.flags as u32,
|
||||
+ InternalFlags::from_extra0(params.internal_flags)
|
||||
+ .ok_or(Error::new(EINVAL))?,
|
||||
+ token,
|
||||
+ ),
|
||||
+ ))));
|
||||
+ }
|
||||
+
|
||||
const EXPECTED: &[u8] = b"create-scheme";
|
||||
let mut buf = [0u8; EXPECTED.len()];
|
||||
|
||||
diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs
|
||||
index 47588e1..1bdd6cc 100644
|
||||
--- a/src/scheme/proc.rs
|
||||
+++ b/src/scheme/proc.rs
|
||||
@@ -849,17 +873,17 @@ impl KernelScheme for ProcScheme {
|
||||
}
|
||||
}
|
||||
fn extract_scheme_number(fd: usize, token: &mut CleanLockToken) -> Result<(KernelSchemes, usize)> {
|
||||
- let (scheme_id, number) = {
|
||||
+ let desc = {
|
||||
let current_lock = context::current();
|
||||
let mut current = current_lock.read(token.token());
|
||||
- let (context, mut token) = current.token_split();
|
||||
+ let (context, mut context_token) = current.token_split();
|
||||
let file_descriptor = context
|
||||
- .get_file(FileHandle::from(fd), &mut token)
|
||||
+ .get_file(FileHandle::from(fd), &mut context_token)
|
||||
.ok_or(Error::new(EBADF))?;
|
||||
- let desc = file_descriptor.description.read(token.token());
|
||||
- (desc.scheme, desc.number)
|
||||
+ *file_descriptor.description.read(context_token.token())
|
||||
};
|
||||
- let scheme = scheme::get_scheme(token.token(), scheme_id)?;
|
||||
+ let scheme = desc.get_scheme(token)?;
|
||||
+ let number = desc.number;
|
||||
|
||||
Ok((scheme, number))
|
||||
}
|
||||
diff --git a/src/scheme/user.rs b/src/scheme/user.rs
|
||||
index b901302..dfbf66b 100644
|
||||
--- a/src/scheme/user.rs
|
||||
+++ b/src/scheme/user.rs
|
||||
@@ -80,6 +80,7 @@ const ONE: NonZeroUsize = match NonZeroUsize::new(1) {
|
||||
Some(one) => one,
|
||||
None => unreachable!(),
|
||||
};
|
||||
+const MAX_SPURIOUS_WAKEUPS: usize = 100;
|
||||
|
||||
enum ParsedCqe {
|
||||
TriggerFevent {
|
||||
@@ -209,6 +210,8 @@ impl UserInner {
|
||||
caller_responsible: &mut PageSpan,
|
||||
token: &mut CleanLockToken,
|
||||
) -> Result<Response> {
|
||||
+ let mut remaining_spurious_wakeups = MAX_SPURIOUS_WAKEUPS;
|
||||
+
|
||||
{
|
||||
// Disable preemption to avoid context switches between setting the
|
||||
// process state and sending the scheme request. The process is made
|
||||
@@ -261,7 +264,10 @@ impl UserInner {
|
||||
};
|
||||
|
||||
let states = self.states.lock(token.token());
|
||||
- let (mut states, mut token) = states.into_split();
|
||||
+ let (mut states, mut state_token) = states.into_split();
|
||||
+ let mut timed_out_descriptions = None;
|
||||
+ let mut remove_state = false;
|
||||
+ let mut timed_out = false;
|
||||
match states.get_mut(sqe.tag as usize) {
|
||||
// invalid state
|
||||
None => return Err(Error::new(EBADFD)),
|
||||
@@ -274,24 +280,35 @@ impl UserInner {
|
||||
fds,
|
||||
} => {
|
||||
let maybe_eintr =
|
||||
- eintr_if_sigkill(&mut callee_responsible, &mut token.token());
|
||||
- *o = State::Waiting {
|
||||
- canceling: true,
|
||||
- callee_responsible,
|
||||
- context,
|
||||
- fds,
|
||||
- };
|
||||
+ eintr_if_sigkill(&mut callee_responsible, &mut state_token.token());
|
||||
|
||||
- maybe_eintr?;
|
||||
+ if maybe_eintr.is_ok() {
|
||||
+ remaining_spurious_wakeups =
|
||||
+ remaining_spurious_wakeups.saturating_sub(1);
|
||||
+ }
|
||||
+
|
||||
+ if maybe_eintr.is_ok() && remaining_spurious_wakeups == 0 {
|
||||
+ timed_out_descriptions = Some(Self::collect_descriptions_to_close(fds));
|
||||
+ remove_state = true;
|
||||
+ } else {
|
||||
+ *o = State::Waiting {
|
||||
+ canceling: true,
|
||||
+ callee_responsible,
|
||||
+ context,
|
||||
+ fds,
|
||||
+ };
|
||||
+ }
|
||||
|
||||
- context::current()
|
||||
- .write(token.token())
|
||||
- .block("UserInner::call (woken up after cancelation request)");
|
||||
+ maybe_eintr?;
|
||||
|
||||
- // We do not want to drop the lock before blocking
|
||||
- // as if we get preempted in between we might miss a
|
||||
- // wakeup.
|
||||
- drop(states);
|
||||
+ if remove_state {
|
||||
+ states.remove(sqe.tag as usize);
|
||||
+ timed_out = true;
|
||||
+ } else {
|
||||
+ context::current()
|
||||
+ .write(state_token.token())
|
||||
+ .block("UserInner::call (woken up after cancelation request)");
|
||||
+ }
|
||||
}
|
||||
// spurious wakeup
|
||||
State::Waiting {
|
||||
@@ -300,60 +317,76 @@ impl UserInner {
|
||||
context,
|
||||
mut callee_responsible,
|
||||
} => {
|
||||
- let maybe_eintr = eintr_if_sigkill(&mut callee_responsible, &mut token);
|
||||
let current_context = context::current();
|
||||
+ let maybe_eintr =
|
||||
+ eintr_if_sigkill(&mut callee_responsible, &mut state_token);
|
||||
+
|
||||
+ if maybe_eintr.is_ok() {
|
||||
+ remaining_spurious_wakeups =
|
||||
+ remaining_spurious_wakeups.saturating_sub(1);
|
||||
+ }
|
||||
|
||||
- *o = State::Waiting {
|
||||
- // Currently we treat all spurious wakeups to have the same behavior
|
||||
- // as signals (i.e., we send a cancellation request). It is not something
|
||||
- // that should happen, but it certainly can happen, for example if a context
|
||||
- // is awoken through its thread handle without setting any sig bits, or if the
|
||||
- // caller clears its own sig bits. If it actually is a signal, then it is the
|
||||
- // intended behavior.
|
||||
- canceling: true,
|
||||
- fds,
|
||||
- context,
|
||||
- callee_responsible,
|
||||
- };
|
||||
+ if maybe_eintr.is_ok() && remaining_spurious_wakeups == 0 {
|
||||
+ timed_out_descriptions = Some(Self::collect_descriptions_to_close(fds));
|
||||
+ remove_state = true;
|
||||
+ } else {
|
||||
+ *o = State::Waiting {
|
||||
+ // Currently we treat all spurious wakeups to have the same behavior
|
||||
+ // as signals (i.e., we send a cancellation request). It is not something
|
||||
+ // that should happen, but it certainly can happen, for example if a context
|
||||
+ // is awoken through its thread handle without setting any sig bits, or if the
|
||||
+ // caller clears its own sig bits. If it actually is a signal, then it is the
|
||||
+ // intended behavior.
|
||||
+ canceling: true,
|
||||
+ fds,
|
||||
+ context,
|
||||
+ callee_responsible,
|
||||
+ };
|
||||
+ }
|
||||
|
||||
maybe_eintr?;
|
||||
|
||||
- // We do not want to preempt between sending the
|
||||
- // cancellation and blocking again where we might
|
||||
- // miss a wakeup.
|
||||
- let mut preempt = PreemptGuardL1::new(¤t_context, &mut token);
|
||||
- let token = preempt.token();
|
||||
-
|
||||
- self.todo.send_locked(
|
||||
- Sqe {
|
||||
- opcode: Opcode::Cancel as u8,
|
||||
- sqe_flags: SqeFlags::ONEWAY,
|
||||
- tag: sqe.tag,
|
||||
- ..Default::default()
|
||||
- },
|
||||
- token.token(),
|
||||
- );
|
||||
- event::trigger_locked(
|
||||
- self.root_id,
|
||||
- self.scheme_id.get(),
|
||||
- EVENT_READ,
|
||||
- token.token(),
|
||||
- );
|
||||
-
|
||||
- // 1. If cancellation was requested and arrived
|
||||
- // before the scheme processed the request, an
|
||||
- // acknowledgement will be sent back after the
|
||||
- // cancellation is processed and we will be woken up
|
||||
- // again. State will be State::Responded then.
|
||||
- //
|
||||
- // 2. If cancellation was requested but the scheme
|
||||
- // already processed the request, we will receive
|
||||
- // the actual response next and woken up again.
|
||||
- // State will be State::Responded then.
|
||||
- context::current()
|
||||
- .write(token.token())
|
||||
- .block("UserInner::call (spurious wakeup)");
|
||||
- drop(states);
|
||||
+ if remove_state {
|
||||
+ states.remove(sqe.tag as usize);
|
||||
+ timed_out = true;
|
||||
+ } else {
|
||||
+ // We do not want to preempt between sending the
|
||||
+ // cancellation and blocking again where we might
|
||||
+ // miss a wakeup.
|
||||
+ let mut preempt =
|
||||
+ PreemptGuardL1::new(¤t_context, &mut state_token);
|
||||
+ let token = preempt.token();
|
||||
+
|
||||
+ self.todo.send_locked(
|
||||
+ Sqe {
|
||||
+ opcode: Opcode::Cancel as u8,
|
||||
+ sqe_flags: SqeFlags::ONEWAY,
|
||||
+ tag: sqe.tag,
|
||||
+ ..Default::default()
|
||||
+ },
|
||||
+ token.token(),
|
||||
+ );
|
||||
+ event::trigger_locked(
|
||||
+ self.root_id,
|
||||
+ self.scheme_id.get(),
|
||||
+ EVENT_READ,
|
||||
+ token.token(),
|
||||
+ );
|
||||
+
|
||||
+ // 1. If cancellation was requested and arrived
|
||||
+ // before the scheme processed the request, an
|
||||
+ // acknowledgement will be sent back after the
|
||||
+ // cancellation is processed and we will be woken up
|
||||
+ // again. State will be State::Responded then.
|
||||
+ //
|
||||
+ // 2. If cancellation was requested but the scheme
|
||||
+ // already processed the request, we will receive
|
||||
+ // the actual response next and woken up again.
|
||||
+ // State will be State::Responded then.
|
||||
+ context::current()
|
||||
+ .write(token.token())
|
||||
+ .block("UserInner::call (spurious wakeup)");
|
||||
+ }
|
||||
}
|
||||
|
||||
// invalid state
|
||||
@@ -368,6 +401,68 @@ impl UserInner {
|
||||
}
|
||||
},
|
||||
}
|
||||
+
|
||||
+ if let Some(descriptions) = timed_out_descriptions {
|
||||
+ drop(states);
|
||||
+ for desc in descriptions {
|
||||
+ let _ = desc.try_close(token);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if timed_out {
|
||||
+ return Err(Error::new(ETIMEDOUT));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ fn collect_descriptions_to_close(
|
||||
+ fds: Vec<Arc<LockedFileDescription>>,
|
||||
+ ) -> Vec<FileDescription> {
|
||||
+ fds.into_iter()
|
||||
+ .filter_map(|fd| Arc::try_unwrap(fd).ok())
|
||||
+ .map(RwLock::into_inner)
|
||||
+ .collect()
|
||||
+ }
|
||||
+
|
||||
+ pub fn fail_pending_calls(&self, token: &mut CleanLockToken) {
|
||||
+ let descriptions_to_close = {
|
||||
+ let mut states_lock = self.states.lock(token.token());
|
||||
+ let (states, mut lock_token) = states_lock.token_split();
|
||||
+ let mut descriptions_to_close = Vec::new();
|
||||
+ let mut states_to_remove = Vec::new();
|
||||
+
|
||||
+ for (id, state) in states.iter_mut() {
|
||||
+ match mem::replace(state, State::Placeholder) {
|
||||
+ State::Waiting { context, fds, .. } => {
|
||||
+ descriptions_to_close.extend(Self::collect_descriptions_to_close(fds));
|
||||
+
|
||||
+ match context.upgrade() {
|
||||
+ Some(context) => {
|
||||
+ *state = State::Responded(Response::Regular(
|
||||
+ Err(Error::new(ENODEV)),
|
||||
+ 0,
|
||||
+ false,
|
||||
+ ));
|
||||
+ context.write(lock_token.token()).unblock();
|
||||
+ }
|
||||
+ None => states_to_remove.push(id),
|
||||
+ }
|
||||
+ }
|
||||
+ old_state => *state = old_state,
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ for id in states_to_remove {
|
||||
+ states.remove(id);
|
||||
+ }
|
||||
+
|
||||
+ descriptions_to_close
|
||||
+ };
|
||||
+
|
||||
+ for desc in descriptions_to_close {
|
||||
+ let _ = desc.try_close(token);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1283,6 +1376,7 @@ impl UserInner {
|
||||
}
|
||||
|
||||
pub fn into_drop(self, token: &mut CleanLockToken) {
|
||||
+ self.fail_pending_calls(token);
|
||||
self.todo.condition.into_drop(token);
|
||||
}
|
||||
}
|
||||
diff --git a/src/syscall/fs.rs b/src/syscall/fs.rs
|
||||
index bf98464..10c6a92 100644
|
||||
--- a/src/syscall/fs.rs
|
||||
+++ b/src/syscall/fs.rs
|
||||
@@ -12,7 +12,7 @@ use crate::{
|
||||
memory::{AddrSpace, GenericFlusher, Grant, PageSpan, TlbShootdownActions},
|
||||
},
|
||||
memory::{Page, VirtualAddress, PAGE_SIZE},
|
||||
- scheme::{self, FileHandle, KernelScheme, OpenResult, StrOrBytes},
|
||||
+ scheme::{FileHandle, KernelScheme, OpenResult, StrOrBytes},
|
||||
sync::{CleanLockToken, RwLock},
|
||||
syscall::{data::Stat, error::*, flag::*},
|
||||
};
|
||||
@@ -45,7 +45,7 @@ pub fn file_op_generic_ext<T>(
|
||||
(file, desc)
|
||||
};
|
||||
|
||||
- let scheme = scheme::get_scheme(token.token(), desc.scheme)?;
|
||||
+ let scheme = desc.get_scheme(token)?;
|
||||
|
||||
op(&*scheme, file.description, desc, token)
|
||||
}
|
||||
@@ -73,14 +73,18 @@ pub fn openat(
|
||||
) -> Result<FileHandle> {
|
||||
let path_buf = copy_path_to_buf(raw_path, PATH_MAX)?;
|
||||
|
||||
- let (scheme_id, number) = {
|
||||
+ let desc = {
|
||||
let current_lock = context::current();
|
||||
let mut current = current_lock.read(token.token());
|
||||
- let (context, mut token) = current.token_split();
|
||||
- let pipe = context.get_file(fh, &mut token).ok_or(Error::new(EBADF))?;
|
||||
- let desc = pipe.description.read(token.token());
|
||||
- (desc.scheme, desc.number)
|
||||
+ let (context, mut context_token) = current.token_split();
|
||||
+ let pipe = context
|
||||
+ .get_file(fh, &mut context_token)
|
||||
+ .ok_or(Error::new(EBADF))?;
|
||||
+ *pipe.description.read(context_token.token())
|
||||
};
|
||||
+ let scheme = desc.get_scheme(token)?;
|
||||
+ let number = desc.number;
|
||||
+ let scheme_id = desc.scheme;
|
||||
|
||||
let caller_ctx = context::current()
|
||||
.read(token.token())
|
||||
@@ -88,8 +92,6 @@ pub fn openat(
|
||||
.filter_uid_gid(euid, egid);
|
||||
|
||||
let new_description = {
|
||||
- let scheme = scheme::get_scheme(token.token(), scheme_id)?;
|
||||
-
|
||||
let res = scheme.kopenat(
|
||||
number,
|
||||
StrOrBytes::from_str(&path_buf),
|
||||
@@ -101,13 +103,14 @@ pub fn openat(
|
||||
|
||||
match res? {
|
||||
OpenResult::SchemeLocal(number, internal_flags) => {
|
||||
- Arc::new(RwLock::new(FileDescription {
|
||||
- offset: 0,
|
||||
- internal_flags,
|
||||
- scheme: scheme_id,
|
||||
+ Arc::new(RwLock::new(FileDescription::new(
|
||||
+ scheme_id,
|
||||
number,
|
||||
- flags: (flags & !O_CLOEXEC) as u32,
|
||||
- }))
|
||||
+ 0,
|
||||
+ (flags & !O_CLOEXEC) as u32,
|
||||
+ internal_flags,
|
||||
+ token,
|
||||
+ )))
|
||||
}
|
||||
OpenResult::External(desc) => desc,
|
||||
}
|
||||
@@ -137,16 +140,17 @@ pub fn unlinkat(
|
||||
) -> Result<()> {
|
||||
let path_buf = copy_path_to_buf(raw_path, PATH_MAX)?;
|
||||
|
||||
- let (number, scheme_id) = {
|
||||
+ let desc = {
|
||||
let current_lock = context::current();
|
||||
let mut current = current_lock.read(token.token());
|
||||
- let (context, mut token) = current.token_split();
|
||||
- let pipe = context.get_file(fh, &mut token).ok_or(Error::new(EBADF))?;
|
||||
- let desc = pipe.description.read(token.token());
|
||||
- (desc.number, desc.scheme)
|
||||
+ let (context, mut context_token) = current.token_split();
|
||||
+ let pipe = context
|
||||
+ .get_file(fh, &mut context_token)
|
||||
+ .ok_or(Error::new(EBADF))?;
|
||||
+ *pipe.description.read(context_token.token())
|
||||
};
|
||||
-
|
||||
- let scheme = scheme::get_scheme(token.token(), scheme_id)?;
|
||||
+ let number = desc.number;
|
||||
+ let scheme = desc.get_scheme(token)?;
|
||||
|
||||
let caller_ctx = context::current()
|
||||
.read(token.token())
|
||||
@@ -199,17 +203,18 @@ fn duplicate_file(
|
||||
let description = { *file.description.read(token.token()) };
|
||||
|
||||
let new_description = {
|
||||
- let scheme = scheme::get_scheme(token.token(), description.scheme)?;
|
||||
+ let scheme = description.get_scheme(token)?;
|
||||
|
||||
match scheme.kdup(description.number, user_buf, caller_ctx, token)? {
|
||||
OpenResult::SchemeLocal(number, internal_flags) => {
|
||||
- Arc::new(RwLock::new(FileDescription {
|
||||
- offset: 0,
|
||||
- internal_flags,
|
||||
- scheme: description.scheme,
|
||||
+ Arc::new(RwLock::new(FileDescription::new(
|
||||
+ description.scheme,
|
||||
number,
|
||||
- flags: description.flags,
|
||||
- }))
|
||||
+ 0,
|
||||
+ description.flags,
|
||||
+ internal_flags,
|
||||
+ token,
|
||||
+ )))
|
||||
}
|
||||
OpenResult::External(desc) => desc,
|
||||
}
|
||||
@@ -296,11 +301,10 @@ fn call_normal(
|
||||
}
|
||||
.ok_or(Error::new(EBADF))?;
|
||||
|
||||
- let (scheme_id, number) = {
|
||||
- let desc = file.description.read(token.token());
|
||||
- (desc.scheme, desc.number)
|
||||
+ let (scheme, number) = {
|
||||
+ let desc = *file.description.read(token.token());
|
||||
+ (desc.get_scheme(token)?, desc.number)
|
||||
};
|
||||
- let scheme = scheme::get_scheme(token.token(), scheme_id)?;
|
||||
|
||||
if flags.contains(CallFlags::STD_FS) {
|
||||
scheme.translate_std_fs_call(number, file.description, payload, flags, metadata, token)
|
||||
@@ -341,28 +345,28 @@ fn fdwrite_inner(
|
||||
) -> Result<usize> {
|
||||
// TODO: Ensure deadlocks can't happen
|
||||
let (scheme, number, descs_to_send) = {
|
||||
- let (scheme, number) = {
|
||||
+ let desc = {
|
||||
let current_lock = context::current();
|
||||
let mut current = current_lock.read(token.token());
|
||||
- let (context, mut token) = current.token_split();
|
||||
+ let (context, mut context_token) = current.token_split();
|
||||
let file_descriptor = context
|
||||
- .get_file(socket, &mut token)
|
||||
+ .get_file(socket, &mut context_token)
|
||||
.ok_or(Error::new(EBADF))?;
|
||||
- let desc = &file_descriptor.description.read(token.token());
|
||||
- (desc.scheme, desc.number)
|
||||
+ *file_descriptor.description.read(context_token.token())
|
||||
};
|
||||
- let scheme = scheme::get_scheme(token.token(), scheme)?;
|
||||
+ let scheme = desc.get_scheme(token)?;
|
||||
+ let number = desc.number;
|
||||
|
||||
let current_lock = context::current();
|
||||
let mut current = current_lock.read(token.token());
|
||||
- let (context, mut token) = current.token_split();
|
||||
+ let (context, mut context_token) = current.token_split();
|
||||
(
|
||||
scheme,
|
||||
number,
|
||||
if flags.contains(CallFlags::FD_CLONE) {
|
||||
- context.bulk_get_files(&target_fds, &mut token)
|
||||
+ context.bulk_get_files(&target_fds, &mut context_token)
|
||||
} else {
|
||||
- context.bulk_remove_files(&target_fds, &mut token)
|
||||
+ context.bulk_remove_files(&target_fds, &mut context_token)
|
||||
}?
|
||||
.into_iter()
|
||||
.map(|f| f.description)
|
||||
@@ -395,18 +399,22 @@ fn call_fdread(
|
||||
metadata: &[u64],
|
||||
token: &mut CleanLockToken,
|
||||
) -> Result<usize> {
|
||||
+ let desc = {
|
||||
+ let current_lock = context::current();
|
||||
+ let mut current = current_lock.read(token.token());
|
||||
+ let (context, mut context_token) = current.token_split();
|
||||
+ let file_descriptor = context
|
||||
+ .get_file(fd, &mut context_token)
|
||||
+ .ok_or(Error::new(EBADF))?;
|
||||
+ *file_descriptor.description.read(context_token.token())
|
||||
+ };
|
||||
let (scheme, number) = {
|
||||
- let (scheme, number) = {
|
||||
- let current_lock = context::current();
|
||||
- let mut current = current_lock.read(token.token());
|
||||
- let (context, mut token) = current.token_split();
|
||||
- let file_descriptor = context.get_file(fd, &mut token).ok_or(Error::new(EBADF))?;
|
||||
- let desc = file_descriptor.description.read(token.token());
|
||||
- (desc.scheme, desc.number)
|
||||
- };
|
||||
- let scheme = scheme::get_scheme(token.token(), scheme)?;
|
||||
-
|
||||
- (scheme, number)
|
||||
+ let scheme = desc.get_scheme(token)?;
|
||||
+ let number = desc.number;
|
||||
+ (
|
||||
+ scheme,
|
||||
+ number,
|
||||
+ )
|
||||
};
|
||||
|
||||
scheme.kfdread(number, payload, flags, metadata, token)
|
||||
@@ -440,9 +448,9 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize, token: &mut CleanLockToken)
|
||||
}
|
||||
.ok_or(Error::new(EBADF))?;
|
||||
|
||||
- let (scheme_id, number, flags) = {
|
||||
- let desc = file.description.write(token.token());
|
||||
- (desc.scheme, desc.number, desc.flags)
|
||||
+ let (number, flags, desc) = {
|
||||
+ let desc = *file.description.read(token.token());
|
||||
+ (desc.number, desc.flags, desc)
|
||||
};
|
||||
|
||||
if cmd == F_DUPFD || cmd == F_DUPFD_CLOEXEC {
|
||||
@@ -460,7 +468,7 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize, token: &mut CleanLockToken)
|
||||
|
||||
// Communicate fcntl with scheme
|
||||
if cmd != F_GETFD && cmd != F_SETFD {
|
||||
- let scheme = scheme::get_scheme(token.token(), scheme_id)?;
|
||||
+ let scheme = desc.get_scheme(token)?;
|
||||
|
||||
scheme.fcntl(number, cmd, arg, token)?;
|
||||
};
|
||||
@@ -518,13 +526,11 @@ pub fn flink(fd: FileHandle, raw_path: UserSliceRo, token: &mut CleanLockToken)
|
||||
let path = RedoxPath::from_absolute(&path_buf).ok_or(Error::new(EINVAL))?;
|
||||
let (_, reference) = path.as_parts().ok_or(Error::new(EINVAL))?;
|
||||
|
||||
- let (number, scheme_id) = {
|
||||
- let desc = file.description.read(token.token());
|
||||
- (desc.number, desc.scheme)
|
||||
+ let (number, scheme) = {
|
||||
+ let desc = *file.description.read(token.token());
|
||||
+ (desc.number, desc.get_scheme(token)?)
|
||||
};
|
||||
|
||||
- let scheme = scheme::get_scheme(token.token(), scheme_id)?;
|
||||
-
|
||||
// TODO: Check EXDEV.
|
||||
/*
|
||||
if scheme_id != description.scheme {
|
||||
@@ -554,13 +560,11 @@ pub fn frename(fd: FileHandle, raw_path: UserSliceRo, token: &mut CleanLockToken
|
||||
let path = RedoxPath::from_absolute(&path_buf).ok_or(Error::new(EINVAL))?;
|
||||
let (_, reference) = path.as_parts().ok_or(Error::new(EINVAL))?;
|
||||
|
||||
- let (number, scheme_id) = {
|
||||
- let desc = file.description.read(token.token());
|
||||
- (desc.number, desc.scheme)
|
||||
+ let (number, scheme) = {
|
||||
+ let desc = *file.description.read(token.token());
|
||||
+ (desc.number, desc.get_scheme(token)?)
|
||||
};
|
||||
|
||||
- let scheme = scheme::get_scheme(token.token(), scheme_id)?;
|
||||
-
|
||||
// TODO: Check EXDEV.
|
||||
/*
|
||||
if scheme_id != description.scheme {
|
||||
diff --git a/src/syscall/process.rs b/src/syscall/process.rs
|
||||
index e83da42..78eed9d 100644
|
||||
--- a/src/syscall/process.rs
|
||||
+++ b/src/syscall/process.rs
|
||||
@@ -271,23 +274,26 @@ unsafe fn bootstrap_mem(bootstrap: &crate::startup::Bootstrap) -> &'static [u8]
|
||||
}
|
||||
|
||||
fn insert_fd(scheme: SchemeId, number: usize, cloexec: bool, token: &mut CleanLockToken) -> usize {
|
||||
+ let description = Arc::new(RwLock::new(FileDescription::new(
|
||||
+ scheme,
|
||||
+ number,
|
||||
+ 0,
|
||||
+ (O_CREAT | O_RDWR) as u32,
|
||||
+ InternalFlags::empty(),
|
||||
+ token,
|
||||
+ )));
|
||||
+
|
||||
let current_lock = context::current();
|
||||
let mut current = current_lock.read(token.token());
|
||||
- let (context, mut token) = current.token_split();
|
||||
+ let (context, mut context_token) = current.token_split();
|
||||
context
|
||||
.add_file_min(
|
||||
FileDescriptor {
|
||||
- description: Arc::new(RwLock::new(FileDescription {
|
||||
- scheme,
|
||||
- number,
|
||||
- offset: 0,
|
||||
- flags: (O_CREAT | O_RDWR) as u32,
|
||||
- internal_flags: InternalFlags::empty(),
|
||||
- })),
|
||||
+ description,
|
||||
cloexec,
|
||||
},
|
||||
syscall::flag::UPPER_FDTBL_TAG + scheme.get(),
|
||||
- &mut token,
|
||||
+ &mut context_token,
|
||||
)
|
||||
.expect("failed to insert fd to current context")
|
||||
.get()
|
||||
@@ -0,0 +1,137 @@
|
||||
diff --git a/src/context/context.rs b/src/context/context.rs
|
||||
index c97c516..6d723f4 100644
|
||||
--- a/src/context/context.rs
|
||||
+++ b/src/context/context.rs
|
||||
@@ -148,6 +148,8 @@ pub struct Context {
|
||||
pub euid: u32,
|
||||
pub egid: u32,
|
||||
pub pid: usize,
|
||||
+ /// Supplementary group IDs for access control decisions.
|
||||
+ pub groups: Vec<u32>,
|
||||
|
||||
// See [`PreemptGuard`]
|
||||
//
|
||||
@@ -204,6 +206,7 @@ impl Context {
|
||||
euid: 0,
|
||||
egid: 0,
|
||||
pid: 0,
|
||||
+ groups: Vec::new(),
|
||||
|
||||
#[cfg(feature = "syscall_debug")]
|
||||
syscall_debug_info: crate::syscall::debug::SyscallDebugInfo::default(),
|
||||
@@ -479,6 +482,7 @@ impl Context {
|
||||
uid: self.euid,
|
||||
gid: self.egid,
|
||||
pid: self.pid,
|
||||
+ groups: self.groups.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/src/scheme/mod.rs b/src/scheme/mod.rs
|
||||
index d30272c..9da2b28 100644
|
||||
--- a/src/scheme/mod.rs
|
||||
+++ b/src/scheme/mod.rs
|
||||
@@ -777,6 +777,7 @@ pub struct CallerCtx {
|
||||
pub pid: usize,
|
||||
pub uid: u32,
|
||||
pub gid: u32,
|
||||
+ pub groups: alloc::vec::Vec<u32>,
|
||||
}
|
||||
impl CallerCtx {
|
||||
pub fn filter_uid_gid(self, euid: u32, egid: u32) -> Self {
|
||||
@@ -785,6 +786,7 @@ impl CallerCtx {
|
||||
pid: self.pid,
|
||||
uid: euid,
|
||||
gid: egid,
|
||||
+ groups: self.groups,
|
||||
}
|
||||
} else {
|
||||
self
|
||||
diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs
|
||||
index 47588e1..6ffb256 100644
|
||||
--- a/src/scheme/proc.rs
|
||||
+++ b/src/scheme/proc.rs
|
||||
@@ -105,6 +105,7 @@ enum ContextHandle {
|
||||
// Attr handles, to set ens/euid/egid/pid.
|
||||
Authority,
|
||||
Attr,
|
||||
+ Groups,
|
||||
|
||||
Status {
|
||||
privileged: bool,
|
||||
@@ -261,6 +262,7 @@ impl ProcScheme {
|
||||
let handle = match actual_name {
|
||||
"attrs" => ContextHandle::Attr,
|
||||
"status" => ContextHandle::Status { privileged: true },
|
||||
+ "groups" => ContextHandle::Groups,
|
||||
_ => return Err(Error::new(ENOENT)),
|
||||
};
|
||||
|
||||
@@ -306,6 +308,11 @@ impl ProcScheme {
|
||||
let id = NonZeroUsize::new(NEXT_ID.fetch_add(1, Ordering::Relaxed))
|
||||
.ok_or(Error::new(EMFILE))?;
|
||||
let context = context::spawn(true, Some(id), ret, token)?;
|
||||
+ {
|
||||
+ let parent_groups =
|
||||
+ context::current().read(token.token()).groups.clone();
|
||||
+ context.write(token.token()).groups = parent_groups;
|
||||
+ }
|
||||
HANDLES.write(token.token()).insert(
|
||||
id.get(),
|
||||
Handle {
|
||||
@@ -1271,6 +1278,39 @@ impl ContextHandle {
|
||||
guard.prio = (info.prio as usize).min(39);
|
||||
Ok(size_of::<ProcSchemeAttrs>())
|
||||
}
|
||||
+ Self::Groups => {
|
||||
+ const NGROUPS_MAX: usize = 65536;
|
||||
+ if buf.len() % size_of::<u32>() != 0 {
|
||||
+ return Err(Error::new(EINVAL));
|
||||
+ }
|
||||
+ let count = buf.len() / size_of::<u32>();
|
||||
+ if count > NGROUPS_MAX {
|
||||
+ return Err(Error::new(EINVAL));
|
||||
+ }
|
||||
+ let mut groups = Vec::with_capacity(count);
|
||||
+ for chunk in buf.in_exact_chunks(size_of::<u32>()).take(count) {
|
||||
+ groups.push(chunk.read_u32()?);
|
||||
+ }
|
||||
+ let proc_id = {
|
||||
+ let guard = context.read(token.token());
|
||||
+ guard.owner_proc_id
|
||||
+ };
|
||||
+ {
|
||||
+ let mut guard = context.write(token.token());
|
||||
+ guard.groups = groups.clone();
|
||||
+ }
|
||||
+ if let Some(pid) = proc_id {
|
||||
+ let mut contexts = context::contexts(token.downgrade());
|
||||
+ let (contexts, mut t) = contexts.token_split();
|
||||
+ for context_ref in contexts.iter() {
|
||||
+ let mut ctx = context_ref.write(t.token());
|
||||
+ if ctx.owner_proc_id == Some(pid) {
|
||||
+ ctx.groups = groups.clone();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ Ok(count * size_of::<u32>())
|
||||
+ }
|
||||
ContextHandle::OpenViaDup => {
|
||||
let mut args = buf.usizes();
|
||||
|
||||
@@ -1475,6 +1515,15 @@ impl ContextHandle {
|
||||
debug_name,
|
||||
})
|
||||
}
|
||||
+ Self::Groups => {
|
||||
+ let c = &context.read(token.token());
|
||||
+ let max = buf.len() / size_of::<u32>();
|
||||
+ let count = c.groups.len().min(max);
|
||||
+ for (chunk, gid) in buf.in_exact_chunks(size_of::<u32>()).zip(&c.groups).take(count) {
|
||||
+ chunk.copy_from_slice(&gid.to_ne_bytes())?;
|
||||
+ }
|
||||
+ Ok(count * size_of::<u32>())
|
||||
+ }
|
||||
ContextHandle::Sighandler => {
|
||||
let data = match context.read(token.token()).sig {
|
||||
Some(ref sig) => SetSighandlerData {
|
||||
@@ -0,0 +1,422 @@
|
||||
diff --git a/src/acpi/madt/arch/x86.rs b/src/acpi/madt/arch/x86.rs
|
||||
index 4dc2388..f472c08 100644
|
||||
--- a/src/acpi/madt/arch/x86.rs
|
||||
+++ b/src/acpi/madt/arch/x86.rs
|
||||
@@ -18,6 +18,7 @@ use crate::{
|
||||
|
||||
use super::{Madt, MadtEntry};
|
||||
|
||||
+const AP_SPIN_LIMIT: u32 = 1_000_000;
|
||||
const TRAMPOLINE: usize = 0x8000;
|
||||
static TRAMPOLINE_DATA: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/trampoline"));
|
||||
|
||||
@@ -42,13 +43,17 @@ pub(super) fn init(madt: Madt) {
|
||||
//TODO: do not have writable and executable!
|
||||
let mut mapper = KernelMapper::lock_rw();
|
||||
|
||||
- let result = mapper
|
||||
- .map_phys(
|
||||
- trampoline_page.start_address(),
|
||||
- trampoline_frame.base(),
|
||||
- PageFlags::new().execute(true).write(true),
|
||||
- )
|
||||
- .expect("failed to map trampoline");
|
||||
+ let result = match mapper.map_phys(
|
||||
+ trampoline_page.start_address(),
|
||||
+ trampoline_frame.base(),
|
||||
+ PageFlags::new().execute(true).write(true),
|
||||
+ ) {
|
||||
+ Some(result) => result,
|
||||
+ None => {
|
||||
+ println!("KERNEL AP: failed to map trampoline page, AP bring-up disabled");
|
||||
+ return;
|
||||
+ }
|
||||
+ };
|
||||
|
||||
(result, mapper.table().phys().data())
|
||||
};
|
||||
@@ -72,17 +77,27 @@ pub(super) fn init(madt: Madt) {
|
||||
if u32::from(ap_local_apic.id) == me.get() {
|
||||
debug!(" This is my local APIC");
|
||||
} else if ap_local_apic.flags & 1 == 1 {
|
||||
- let cpu_id = LogicalCpuId::next();
|
||||
-
|
||||
// Allocate a stack
|
||||
- let stack_start = RmmA::phys_to_virt(
|
||||
- allocate_p2frame(4)
|
||||
- .expect("no more frames in acpi stack_start")
|
||||
- .base(),
|
||||
- )
|
||||
- .data();
|
||||
+ let alloc = match allocate_p2frame(4) {
|
||||
+ Some(frame) => frame,
|
||||
+ None => {
|
||||
+ println!("KERNEL AP: CPU {} no memory for stack, skipping", ap_local_apic.id);
|
||||
+ continue;
|
||||
+ }
|
||||
+ };
|
||||
+ let stack_start = RmmA::phys_to_virt(alloc.base()).data();
|
||||
let stack_end = stack_start + (PAGE_SIZE << 4);
|
||||
|
||||
+ let next_cpu = crate::CPU_COUNT.load(Ordering::Relaxed);
|
||||
+ if next_cpu >= crate::cpu_set::MAX_CPU_COUNT {
|
||||
+ println!(
|
||||
+ "KERNEL AP: CPU {} exceeds logical CPU limit, skipping",
|
||||
+ ap_local_apic.id
|
||||
+ );
|
||||
+ continue;
|
||||
+ }
|
||||
+ let cpu_id = LogicalCpuId::new(next_cpu);
|
||||
+
|
||||
let pcr_ptr = crate::arch::gdt::allocate_and_init_pcr(cpu_id, stack_end);
|
||||
|
||||
let idt_ptr = crate::arch::idt::allocate_and_init_idt(cpu_id);
|
||||
@@ -137,13 +152,34 @@ pub(super) fn init(madt: Madt) {
|
||||
local_apic.set_icr(icr);
|
||||
}
|
||||
|
||||
- // Wait for trampoline ready
|
||||
- while unsafe { (*ap_ready.cast::<AtomicU8>()).load(Ordering::SeqCst) } == 0 {
|
||||
+ // Wait for trampoline ready with timeout
|
||||
+ let mut trampoline_ready = false;
|
||||
+ for _ in 0..AP_SPIN_LIMIT {
|
||||
+ if unsafe { (*ap_ready.cast::<AtomicU8>()).load(Ordering::SeqCst) } != 0 {
|
||||
+ trampoline_ready = true;
|
||||
+ break;
|
||||
+ }
|
||||
hint::spin_loop();
|
||||
}
|
||||
- while !AP_READY.load(Ordering::SeqCst) {
|
||||
+ if !trampoline_ready {
|
||||
+ println!("KERNEL AP: CPU {} trampoline timeout, skipping", ap_local_apic.id);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ let mut kernel_ready = false;
|
||||
+ for _ in 0..AP_SPIN_LIMIT {
|
||||
+ if AP_READY.load(Ordering::SeqCst) {
|
||||
+ kernel_ready = true;
|
||||
+ break;
|
||||
+ }
|
||||
hint::spin_loop();
|
||||
}
|
||||
+ if !kernel_ready {
|
||||
+ println!("KERNEL AP: CPU {} AP_READY timeout, skipping", ap_local_apic.id);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ crate::CPU_COUNT.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
RmmA::invalidate_all();
|
||||
}
|
||||
@@ -151,10 +187,12 @@ pub(super) fn init(madt: Madt) {
|
||||
}
|
||||
|
||||
// Unmap trampoline
|
||||
- let (_frame, _, flush) = unsafe {
|
||||
+ if let Some((_frame, _, flush)) = unsafe {
|
||||
KernelMapper::lock_rw()
|
||||
.unmap_phys(trampoline_page.start_address())
|
||||
- .expect("failed to unmap trampoline page")
|
||||
- };
|
||||
- flush.flush();
|
||||
+ } {
|
||||
+ flush.flush();
|
||||
+ } else {
|
||||
+ println!("KERNEL AP: failed to unmap trampoline page (non-fatal)");
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/allocator/mod.rs b/src/allocator/mod.rs
|
||||
index 4fdb0ba..aaa7196 100644
|
||||
--- a/src/allocator/mod.rs
|
||||
+++ b/src/allocator/mod.rs
|
||||
@@ -7,26 +7,40 @@ mod linked_list;
|
||||
/// Size of kernel heap
|
||||
const KERNEL_HEAP_SIZE: usize = ::rmm::MEGABYTE;
|
||||
|
||||
+#[cold]
|
||||
+fn halt_kernel_heap_init(message: &str) -> ! {
|
||||
+ print!("{message}");
|
||||
+ println!("Kernel heap initialization cannot continue. Halting.");
|
||||
+ loop {
|
||||
+ core::hint::spin_loop();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
unsafe fn map_heap(mapper: &mut KernelMapper<true>, offset: usize, size: usize) {
|
||||
let mut flush_all = PageFlushAll::new();
|
||||
|
||||
let heap_start_page = Page::containing_address(VirtualAddress::new(offset));
|
||||
let heap_end_page = Page::containing_address(VirtualAddress::new(offset + size - 1));
|
||||
for page in Page::range_inclusive(heap_start_page, heap_end_page) {
|
||||
- let phys = mapper
|
||||
- .allocator_mut()
|
||||
- .allocate_one()
|
||||
- .expect("failed to allocate kernel heap");
|
||||
+ let phys = match mapper.allocator_mut().allocate_one() {
|
||||
+ Some(phys) => phys,
|
||||
+ None => halt_kernel_heap_init(
|
||||
+ "FATAL: failed to allocate physical frame for kernel heap\n",
|
||||
+ ),
|
||||
+ };
|
||||
let flush = unsafe {
|
||||
- mapper
|
||||
- .map_phys(
|
||||
- page.start_address(),
|
||||
- phys,
|
||||
- PageFlags::new()
|
||||
- .write(true)
|
||||
- .global(cfg!(not(feature = "pti"))),
|
||||
- )
|
||||
- .expect("failed to map kernel heap")
|
||||
+ match mapper.map_phys(
|
||||
+ page.start_address(),
|
||||
+ phys,
|
||||
+ PageFlags::new()
|
||||
+ .write(true)
|
||||
+ .global(cfg!(not(feature = "pti"))),
|
||||
+ ) {
|
||||
+ Some(flush) => flush,
|
||||
+ None => halt_kernel_heap_init(
|
||||
+ "FATAL: failed to map kernel heap virtual page\n",
|
||||
+ ),
|
||||
+ }
|
||||
};
|
||||
flush_all.consume(flush);
|
||||
}
|
||||
diff --git a/src/arch/x86_shared/gdt.rs b/src/arch/x86_shared/gdt.rs
|
||||
index cad344f..f7acae3 100644
|
||||
--- a/src/arch/x86_shared/gdt.rs
|
||||
+++ b/src/arch/x86_shared/gdt.rs
|
||||
@@ -192,6 +192,15 @@ impl ProcessorControlRegion {
|
||||
}
|
||||
}
|
||||
|
||||
+#[cold]
|
||||
+fn halt_pcr_init() -> ! {
|
||||
+ println!("FATAL: failed to allocate physical memory for Processor Control Region");
|
||||
+ println!("Processor startup cannot continue. Halting.");
|
||||
+ loop {
|
||||
+ core::hint::spin_loop();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
pub unsafe fn pcr() -> *mut ProcessorControlRegion {
|
||||
unsafe {
|
||||
// Primitive benchmarking of RDFSBASE and RDGSBASE in userspace, appears to indicate that
|
||||
@@ -375,7 +384,10 @@ pub fn allocate_and_init_pcr(
|
||||
.next_power_of_two()
|
||||
.trailing_zeros();
|
||||
|
||||
- let pcr_frame = crate::memory::allocate_p2frame(alloc_order).expect("failed to allocate PCR");
|
||||
+ let pcr_frame = match crate::memory::allocate_p2frame(alloc_order) {
|
||||
+ Some(frame) => frame,
|
||||
+ None => halt_pcr_init(),
|
||||
+ };
|
||||
let pcr_ptr = RmmA::phys_to_virt(pcr_frame.base()).data() as *mut ProcessorControlRegion;
|
||||
unsafe { core::ptr::write(pcr_ptr, ProcessorControlRegion::new_partial_init(cpu_id)) };
|
||||
|
||||
diff --git a/src/arch/x86_shared/idt.rs b/src/arch/x86_shared/idt.rs
|
||||
index 5006458..47f692f 100644
|
||||
--- a/src/arch/x86_shared/idt.rs
|
||||
+++ b/src/arch/x86_shared/idt.rs
|
||||
@@ -78,6 +78,15 @@ static INIT_BSP_IDT: SyncUnsafeCell<Idt> = SyncUnsafeCell::new(Idt::new());
|
||||
pub(crate) static IDTS: RwLock<HashMap<LogicalCpuId, &'static mut Idt>> =
|
||||
RwLock::new(HashMap::with_hasher(DefaultHashBuilder::new()));
|
||||
|
||||
+#[cold]
|
||||
+fn halt_idt_init() -> ! {
|
||||
+ println!("FATAL: failed to allocate physical pages for backup interrupt stack");
|
||||
+ println!("Interrupt setup cannot continue. Halting.");
|
||||
+ loop {
|
||||
+ core::hint::spin_loop();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
#[inline]
|
||||
pub fn is_reserved(cpu_id: LogicalCpuId, index: u8) -> bool {
|
||||
if cpu_id == LogicalCpuId::BSP {
|
||||
@@ -161,8 +170,10 @@ pub fn allocate_and_init_idt(cpu_id: LogicalCpuId) -> *mut Idt {
|
||||
.or_insert_with(|| Box::leak(Box::new(Idt::new())));
|
||||
|
||||
use crate::memory::{RmmA, RmmArch};
|
||||
- let frames = crate::memory::allocate_p2frame(4)
|
||||
- .expect("failed to allocate pages for backup interrupt stack");
|
||||
+ let frames = match crate::memory::allocate_p2frame(4) {
|
||||
+ Some(frames) => frames,
|
||||
+ None => halt_idt_init(),
|
||||
+ };
|
||||
|
||||
// Physical pages are mapped linearly. So is the linearly mapped virtual memory.
|
||||
let base_address = RmmA::phys_to_virt(frames.base());
|
||||
diff --git a/src/memory/mod.rs b/src/memory/mod.rs
|
||||
index 393ae7e..b4a1aa3 100644
|
||||
--- a/src/memory/mod.rs
|
||||
+++ b/src/memory/mod.rs
|
||||
@@ -754,7 +754,8 @@ pub fn init_mm(allocator: BumpAllocator<RmmA>) {
|
||||
init_sections(allocator);
|
||||
|
||||
unsafe {
|
||||
- let the_frame = allocate_frame().expect("failed to allocate static zeroed frame");
|
||||
+ let the_frame = allocate_frame()
|
||||
+ .expect("KERNEL MEM: failed to allocate static zeroed frame during init_mm - physical memory exhausted");
|
||||
let the_info = get_page_info(the_frame).expect("static zeroed frame had no PageInfo");
|
||||
the_info
|
||||
.refcount
|
||||
@@ -1027,9 +1028,13 @@ pub fn page_fault_handler(
|
||||
let mut token = unsafe { CleanLockToken::new() };
|
||||
match context::memory::try_correcting_page_tables(faulting_page, mode, &mut token) {
|
||||
Ok(()) => return Ok(()),
|
||||
- Err(PfError::Oom) => todo!("oom"),
|
||||
+ Err(PfError::Oom) => {
|
||||
+ debug!("KERNEL PF: OOM during page table correction for {:#x}", faulting_address.data());
|
||||
+ }
|
||||
Err(PfError::Segv | PfError::RecursionLimitExceeded) => (),
|
||||
- Err(PfError::NonfatalInternalError) => todo!(),
|
||||
+ Err(PfError::NonfatalInternalError) => {
|
||||
+ debug!("KERNEL PF: internal error during page table correction for {:#x}", faulting_address.data());
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1038,6 +1043,17 @@ pub fn page_fault_handler(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
+ debug!(
|
||||
+ "KERNEL PF: addr={:#x} ip={:#x} mode={:?} kernel={} user={} write={} instr={}",
|
||||
+ faulting_address.data(),
|
||||
+ stack.ip(),
|
||||
+ mode,
|
||||
+ caused_by_kernel,
|
||||
+ caused_by_user,
|
||||
+ caused_by_write,
|
||||
+ caused_by_instr_fetch,
|
||||
+ );
|
||||
+
|
||||
Err(Segv)
|
||||
}
|
||||
static THE_ZEROED_FRAME: SyncUnsafeCell<Option<(Frame, &'static PageInfo)>> =
|
||||
diff --git a/src/startup/memory.rs b/src/startup/memory.rs
|
||||
index 26922dd..f271200 100644
|
||||
--- a/src/startup/memory.rs
|
||||
+++ b/src/startup/memory.rs
|
||||
@@ -323,7 +323,16 @@ unsafe fn map_memory<A: Arch>(areas: &[MemoryArea], mut bump_allocator: &mut Bum
|
||||
}
|
||||
}
|
||||
|
||||
- let kernel_area = (*MEMORY_MAP.get()).kernel().unwrap();
|
||||
+ let kernel_area = match (*MEMORY_MAP.get()).kernel() {
|
||||
+ Some(area) => area,
|
||||
+ None => {
|
||||
+ println!("FATAL: kernel memory area not found in boot memory map");
|
||||
+ println!("Cannot determine kernel base address. Halting.");
|
||||
+ loop {
|
||||
+ core::hint::spin_loop();
|
||||
+ }
|
||||
+ }
|
||||
+ };
|
||||
let kernel_base = kernel_area.start;
|
||||
let kernel_size = kernel_area.end.saturating_sub(kernel_area.start);
|
||||
// Map kernel at KERNEL_OFFSET
|
||||
diff --git a/src/startup/mod.rs b/src/startup/mod.rs
|
||||
index 8ad3cdf..86aabc2 100644
|
||||
--- a/src/startup/mod.rs
|
||||
+++ b/src/startup/mod.rs
|
||||
@@ -149,6 +149,15 @@ static BOOTSTRAP: spin::Once<Bootstrap> = spin::Once::new();
|
||||
pub(crate) static AP_READY: AtomicBool = AtomicBool::new(false);
|
||||
static BSP_READY: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
+#[cold]
|
||||
+fn halt_boot(message: &str) -> ! {
|
||||
+ print!("{message}");
|
||||
+ println!("Kernel boot cannot continue. Halting.");
|
||||
+ loop {
|
||||
+ hint::spin_loop();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/// This is the kernel entry point for the primary CPU. The arch crate is responsible for calling this
|
||||
pub(crate) fn kmain(bootstrap: Bootstrap) -> ! {
|
||||
let mut token = unsafe { CleanLockToken::new() };
|
||||
@@ -180,9 +189,7 @@ pub(crate) fn kmain(bootstrap: Bootstrap) -> ! {
|
||||
context.euid = 0;
|
||||
context.egid = 0;
|
||||
}
|
||||
- Err(err) => {
|
||||
- panic!("failed to spawn userspace_init: {:?}", err);
|
||||
- }
|
||||
+ Err(_err) => halt_boot("FATAL: failed to spawn first userspace process userspace_init\n"),
|
||||
}
|
||||
|
||||
run_userspace(&mut token)
|
||||
diff --git a/src/syscall/process.rs b/src/syscall/process.rs
|
||||
index e83da42..084b64e 100644
|
||||
--- a/src/syscall/process.rs
|
||||
+++ b/src/syscall/process.rs
|
||||
@@ -33,6 +33,8 @@ pub fn exit_this_context(excp: Option<syscall::Exception>, token: &mut CleanLock
|
||||
let mut close_files;
|
||||
let addrspace_opt;
|
||||
|
||||
+ super::futex::cleanup_current_robust_futexes(token);
|
||||
+
|
||||
let context_lock = context::current();
|
||||
{
|
||||
let mut context = context_lock.write(token.token());
|
||||
@@ -44,6 +46,7 @@ pub fn exit_this_context(excp: Option<syscall::Exception>, token: &mut CleanLock
|
||||
addrspace_opt = context
|
||||
.set_addr_space(None, token.downgrade())
|
||||
.and_then(|a| Arc::try_unwrap(a).ok());
|
||||
+ context.robust_list_head = None;
|
||||
drop(mem::replace(&mut context.syscall_head, SyscallFrame::Dummy));
|
||||
drop(mem::replace(&mut context.syscall_tail, SyscallFrame::Dummy));
|
||||
}
|
||||
@@ -244,7 +247,11 @@ pub unsafe fn usermode_bootstrap(bootstrap: &Bootstrap, token: &mut CleanLockTok
|
||||
.copy_from_slice(bootstrap_slice)
|
||||
.expect("failed to copy memory to bootstrap");
|
||||
|
||||
- let bootstrap_entry = u64::from_le_bytes(bootstrap_slice[0x1a..0x22].try_into().unwrap());
|
||||
+ let bootstrap_entry = if bootstrap_slice.len() >= 0x22 {
|
||||
+ u64::from_le_bytes(bootstrap_slice[0x1a..0x22].try_into().unwrap())
|
||||
+ } else {
|
||||
+ panic!("KERNEL BOOT: bootstrap initfs too small ({} bytes, need at least 34) - cannot determine entry point", bootstrap_slice.len());
|
||||
+ };
|
||||
debug!("Bootstrap entry point: {:X}", bootstrap_entry);
|
||||
assert_ne!(bootstrap_entry, 0);
|
||||
|
||||
@@ -271,23 +278,26 @@ unsafe fn bootstrap_mem(bootstrap: &crate::startup::Bootstrap) -> &'static [u8]
|
||||
}
|
||||
|
||||
fn insert_fd(scheme: SchemeId, number: usize, cloexec: bool, token: &mut CleanLockToken) -> usize {
|
||||
+ let description = Arc::new(RwLock::new(FileDescription::new(
|
||||
+ scheme,
|
||||
+ number,
|
||||
+ 0,
|
||||
+ (O_CREAT | O_RDWR) as u32,
|
||||
+ InternalFlags::empty(),
|
||||
+ token,
|
||||
+ )));
|
||||
+
|
||||
let current_lock = context::current();
|
||||
let mut current = current_lock.read(token.token());
|
||||
- let (context, mut token) = current.token_split();
|
||||
+ let (context, mut context_token) = current.token_split();
|
||||
context
|
||||
.add_file_min(
|
||||
FileDescriptor {
|
||||
- description: Arc::new(RwLock::new(FileDescription {
|
||||
- scheme,
|
||||
- number,
|
||||
- offset: 0,
|
||||
- flags: (O_CREAT | O_RDWR) as u32,
|
||||
- internal_flags: InternalFlags::empty(),
|
||||
- })),
|
||||
+ description,
|
||||
cloexec,
|
||||
},
|
||||
syscall::flag::UPPER_FDTBL_TAG + scheme.get(),
|
||||
- &mut token,
|
||||
+ &mut context_token,
|
||||
)
|
||||
.expect("failed to insert fd to current context")
|
||||
.get()
|
||||
@@ -0,0 +1,13 @@
|
||||
diff --git a/src/context/mod.rs b/src/context/mod.rs
|
||||
index 37c73f5..4f5d60f 100644
|
||||
--- a/src/context/mod.rs
|
||||
+++ b/src/context/mod.rs
|
||||
@@ -22,7 +22,7 @@ use crate::{
|
||||
|
||||
use self::context::Kstack;
|
||||
pub use self::{
|
||||
- context::{BorrowedHtBuf, Context, Status},
|
||||
+ context::{BorrowedHtBuf, Context, SchedPolicy, Status},
|
||||
switch::switch,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
diff --git a/src/lib.rs b/src/lib.rs
|
||||
--- a/src/lib.rs
|
||||
+++ b/src/lib.rs
|
||||
@@ -57,16 +57,151 @@ pub mod start;
|
||||
pub mod sync;
|
||||
|
||||
-use crate::platform::{Allocator, NEWALLOCATOR};
|
||||
+use crate::platform::{Allocator, NEWALLOCATOR, Pal, Sys};
|
||||
|
||||
#[global_allocator]
|
||||
static ALLOCATOR: Allocator = NEWALLOCATOR;
|
||||
+
|
||||
+const MAX_FATAL_BACKTRACE_FRAMES: usize = 16;
|
||||
+const MAX_FATAL_FRAME_STRIDE: usize = 1024 * 1024;
|
||||
+
|
||||
+#[inline(never)]
|
||||
+fn write_process_thread_identity(w: &mut platform::FileWriter) {
|
||||
+ use core::fmt::Write;
|
||||
+
|
||||
+ let pid = Sys::getpid();
|
||||
+ let tid = Sys::gettid();
|
||||
+
|
||||
+ match crate::pthread::current_thread() {
|
||||
+ Some(thread) => {
|
||||
+ let _ = w.write_fmt(format_args!(
|
||||
+ "RELIBC CONTEXT: pid={} tid={} pthread={:#x}\n",
|
||||
+ pid,
|
||||
+ tid,
|
||||
+ thread as *const _ as usize,
|
||||
+ ));
|
||||
+ }
|
||||
+ None => {
|
||||
+ let _ = w.write_fmt(format_args!(
|
||||
+ "RELIBC CONTEXT: pid={} tid={} pthread=<unavailable>\n",
|
||||
+ pid, tid,
|
||||
+ ));
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+#[cfg(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64"))]
|
||||
+#[inline(never)]
|
||||
+fn current_frame_pointer() -> *const usize {
|
||||
+ let frame: *const usize;
|
||||
+
|
||||
+ #[cfg(target_arch = "x86_64")]
|
||||
+ unsafe {
|
||||
+ core::arch::asm!("mov {}, rbp", out(reg) frame, options(nomem, nostack, preserves_flags));
|
||||
+ }
|
||||
+
|
||||
+ #[cfg(target_arch = "x86")]
|
||||
+ unsafe {
|
||||
+ core::arch::asm!("mov {}, ebp", out(reg) frame, options(nomem, nostack, preserves_flags));
|
||||
+ }
|
||||
+
|
||||
+ #[cfg(target_arch = "aarch64")]
|
||||
+ unsafe {
|
||||
+ core::arch::asm!("mov {}, x29", out(reg) frame, options(nomem, nostack, preserves_flags));
|
||||
+ }
|
||||
+
|
||||
+ frame
|
||||
+}
|
||||
+
|
||||
+#[cfg(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64"))]
|
||||
+fn read_backtrace_frame(frame: *const usize) -> Option<(*const usize, usize)> {
|
||||
+ let align = core::mem::align_of::<usize>();
|
||||
+ let frame_addr = frame as usize;
|
||||
+
|
||||
+ if frame.is_null() || frame_addr % align != 0 {
|
||||
+ return None;
|
||||
+ }
|
||||
+
|
||||
+ let next_frame = unsafe { frame.read() } as *const usize;
|
||||
+ let return_address = unsafe { frame.add(1).read() };
|
||||
+
|
||||
+ if return_address == 0 {
|
||||
+ return None;
|
||||
+ }
|
||||
+
|
||||
+ Some((next_frame, return_address))
|
||||
+}
|
||||
+
|
||||
+#[cfg(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64"))]
|
||||
+fn is_sane_next_backtrace_frame(current: *const usize, next: *const usize) -> bool {
|
||||
+ let align = core::mem::align_of::<usize>();
|
||||
+ let current_addr = current as usize;
|
||||
+ let next_addr = next as usize;
|
||||
+
|
||||
+ !next.is_null()
|
||||
+ && next_addr % align == 0
|
||||
+ && next_addr > current_addr
|
||||
+ && next_addr - current_addr <= MAX_FATAL_FRAME_STRIDE
|
||||
+}
|
||||
+
|
||||
+#[inline(never)]
|
||||
+fn write_best_effort_backtrace(w: &mut platform::FileWriter) {
|
||||
+ use core::fmt::Write;
|
||||
+
|
||||
+ let _ = w.write_str("RELIBC: attempting best-effort backtrace\n");
|
||||
+
|
||||
+ #[cfg(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64"))]
|
||||
+ {
|
||||
+ let mut frame = current_frame_pointer();
|
||||
+ let mut wrote_frame = false;
|
||||
+
|
||||
+ for frame_index in 0..MAX_FATAL_BACKTRACE_FRAMES {
|
||||
+ let Some((next_frame, return_address)) = read_backtrace_frame(frame) else {
|
||||
+ break;
|
||||
+ };
|
||||
+
|
||||
+ wrote_frame = true;
|
||||
+ let _ = w.write_fmt(format_args!(
|
||||
+ "RELIBC BACKTRACE[{frame_index:02}]: {:#x}\n",
|
||||
+ return_address,
|
||||
+ ));
|
||||
+
|
||||
+ if !is_sane_next_backtrace_frame(frame, next_frame) {
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ frame = next_frame;
|
||||
+ }
|
||||
+
|
||||
+ if !wrote_frame {
|
||||
+ let _ = w.write_str("RELIBC: backtrace attempt produced no frames\n");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ #[cfg(not(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64")))]
|
||||
+ {
|
||||
+ let _ = w.write_str("RELIBC: backtrace unavailable on this architecture\n");
|
||||
+ }
|
||||
+}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn relibc_panic(pi: &::core::panic::PanicInfo) -> ! {
|
||||
use core::fmt::Write;
|
||||
|
||||
let mut w = platform::FileWriter::new(2);
|
||||
- let _ = w.write_fmt(format_args!("RELIBC PANIC: {}\n", pi));
|
||||
+
|
||||
+ if let Some(location) = pi.location() {
|
||||
+ let _ = w.write_fmt(format_args!(
|
||||
+ "RELIBC PANIC LOCATION: {}:{}:{}\n",
|
||||
+ location.file(),
|
||||
+ location.line(),
|
||||
+ location.column(),
|
||||
+ ));
|
||||
+ } else {
|
||||
+ let _ = w.write_str("RELIBC PANIC LOCATION: <unavailable>\n");
|
||||
+ }
|
||||
+
|
||||
+ write_process_thread_identity(&mut w);
|
||||
+ let _ = w.write_fmt(format_args!("RELIBC PANIC: {}\n", pi));
|
||||
|
||||
core::intrinsics::abort();
|
||||
}
|
||||
@@ -95,23 +235,28 @@ pub extern "C" fn rust_oom(layout: ::core::alloc::Layout) -> ! {
|
||||
|
||||
let mut w = platform::FileWriter::new(2);
|
||||
let _ = w.write_fmt(format_args!(
|
||||
- "RELIBC OOM: {} bytes aligned to {} bytes\n",
|
||||
+ "RELIBC OOM: {} bytes aligned to {} bytes - process will abort\n",
|
||||
layout.size(),
|
||||
layout.align()
|
||||
));
|
||||
+ write_process_thread_identity(&mut w);
|
||||
+ write_best_effort_backtrace(&mut w);
|
||||
|
||||
core::intrinsics::abort();
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[allow(non_snake_case)]
|
||||
#[linkage = "weak"]
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn _Unwind_Resume() -> ! {
|
||||
use core::fmt::Write;
|
||||
|
||||
let mut w = platform::FileWriter::new(2);
|
||||
- let _ = w.write_str("_Unwind_Resume\n");
|
||||
+ let _ = w.write_str(
|
||||
+ "RELIBC: _Unwind_Resume called - exception propagation failed, aborting\n",
|
||||
+ );
|
||||
+ write_process_thread_identity(&mut w);
|
||||
|
||||
core::intrinsics::abort();
|
||||
}
|
||||
@@ -0,0 +1,685 @@
|
||||
diff --git a/drivers/acpid/src/main.rs b/drivers/acpid/src/main.rs
|
||||
index 059254b3..a3f5f996 100644
|
||||
--- a/drivers/acpid/src/main.rs
|
||||
+++ b/drivers/acpid/src/main.rs
|
||||
@@ -3,6 +3,7 @@ use std::fs::File;
|
||||
use std::mem;
|
||||
use std::ops::ControlFlow;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
+use std::process;
|
||||
use std::sync::Arc;
|
||||
|
||||
use ::acpi::aml::op_region::{RegionHandler, RegionSpace};
|
||||
@@ -17,6 +18,58 @@ mod ec;
|
||||
|
||||
mod scheme;
|
||||
|
||||
+fn parse_physaddrs(sdt: &self::acpi::Sdt) -> Vec<u64> {
|
||||
+ match &sdt.signature {
|
||||
+ b"RSDT" => {
|
||||
+ let chunks = sdt.data().chunks_exact(mem::size_of::<u32>());
|
||||
+ if !chunks.remainder().is_empty() {
|
||||
+ eprintln!(
|
||||
+ "acpid: malformed RSDT length {}: expected 4-byte entries",
|
||||
+ sdt.data().len()
|
||||
+ );
|
||||
+ process::exit(1);
|
||||
+ }
|
||||
+
|
||||
+ chunks
|
||||
+ .map(|chunk| match <[u8; mem::size_of::<u32>()]>::try_from(chunk) {
|
||||
+ Ok(bytes) => u32::from_le_bytes(bytes) as u64,
|
||||
+ Err(_) => {
|
||||
+ eprintln!("acpid: failed to decode RSDT physical address entry");
|
||||
+ process::exit(1);
|
||||
+ }
|
||||
+ })
|
||||
+ .collect()
|
||||
+ }
|
||||
+ b"XSDT" => {
|
||||
+ let chunks = sdt.data().chunks_exact(mem::size_of::<u64>());
|
||||
+ if !chunks.remainder().is_empty() {
|
||||
+ eprintln!(
|
||||
+ "acpid: malformed XSDT length {}: expected 8-byte entries",
|
||||
+ sdt.data().len()
|
||||
+ );
|
||||
+ process::exit(1);
|
||||
+ }
|
||||
+
|
||||
+ chunks
|
||||
+ .map(|chunk| match <[u8; mem::size_of::<u64>()]>::try_from(chunk) {
|
||||
+ Ok(bytes) => u64::from_le_bytes(bytes),
|
||||
+ Err(_) => {
|
||||
+ eprintln!("acpid: failed to decode XSDT physical address entry");
|
||||
+ process::exit(1);
|
||||
+ }
|
||||
+ })
|
||||
+ .collect()
|
||||
+ }
|
||||
+ signature => {
|
||||
+ eprintln!(
|
||||
+ "acpid: expected [RX]SDT from kernel, got {:?}",
|
||||
+ String::from_utf8_lossy(signature)
|
||||
+ );
|
||||
+ process::exit(1);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
common::setup_logging(
|
||||
"misc",
|
||||
@@ -29,7 +82,10 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
log::info!("acpid start");
|
||||
|
||||
let rxsdt_raw_data: Arc<[u8]> = std::fs::read("/scheme/kernel.acpi/rxsdt")
|
||||
- .expect("acpid: failed to read `/scheme/kernel.acpi/rxsdt`")
|
||||
+ .unwrap_or_else(|err| {
|
||||
+ eprintln!("acpid: failed to read `/scheme/kernel.acpi/rxsdt`: {err}");
|
||||
+ process::exit(1);
|
||||
+ })
|
||||
.into();
|
||||
|
||||
if rxsdt_raw_data.is_empty() {
|
||||
@@ -38,84 +94,84 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
- let sdt = self::acpi::Sdt::new(rxsdt_raw_data).expect("acpid: failed to parse [RX]SDT");
|
||||
-
|
||||
- let mut thirty_two_bit;
|
||||
- let mut sixty_four_bit;
|
||||
-
|
||||
- let physaddrs_iter = match &sdt.signature {
|
||||
- b"RSDT" => {
|
||||
- thirty_two_bit = sdt
|
||||
- .data()
|
||||
- .chunks(mem::size_of::<u32>())
|
||||
- // TODO: With const generics, the compiler has some way of doing this for static sizes.
|
||||
- .map(|chunk| <[u8; mem::size_of::<u32>()]>::try_from(chunk).unwrap())
|
||||
- .map(|chunk| u32::from_le_bytes(chunk))
|
||||
- .map(u64::from);
|
||||
-
|
||||
- &mut thirty_two_bit as &mut dyn Iterator<Item = u64>
|
||||
- }
|
||||
- b"XSDT" => {
|
||||
- sixty_four_bit = sdt
|
||||
- .data()
|
||||
- .chunks(mem::size_of::<u64>())
|
||||
- .map(|chunk| <[u8; mem::size_of::<u64>()]>::try_from(chunk).unwrap())
|
||||
- .map(|chunk| u64::from_le_bytes(chunk));
|
||||
-
|
||||
- &mut sixty_four_bit as &mut dyn Iterator<Item = u64>
|
||||
- }
|
||||
- _ => panic!("acpid: expected [RX]SDT from kernel to be either of those"),
|
||||
- };
|
||||
+ let sdt = self::acpi::Sdt::new(rxsdt_raw_data).unwrap_or_else(|err| {
|
||||
+ eprintln!("acpid: failed to parse [RX]SDT: {err}");
|
||||
+ process::exit(1);
|
||||
+ });
|
||||
+ let physaddrs = parse_physaddrs(&sdt);
|
||||
|
||||
let region_handlers: Vec<(RegionSpace, Box<dyn RegionHandler + 'static>)> = vec![
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
(RegionSpace::EmbeddedControl, Box::new(ec::Ec::new())),
|
||||
];
|
||||
- let acpi_context = self::acpi::AcpiContext::init(physaddrs_iter, region_handlers);
|
||||
+ let acpi_context = self::acpi::AcpiContext::init(physaddrs.into_iter(), region_handlers);
|
||||
|
||||
// TODO: I/O permission bitmap?
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
- common::acquire_port_io_rights().expect("acpid: failed to set I/O privilege level to Ring 3");
|
||||
+ common::acquire_port_io_rights().unwrap_or_else(|err| {
|
||||
+ eprintln!("acpid: failed to set I/O privilege level to Ring 3: {err}");
|
||||
+ process::exit(1);
|
||||
+ });
|
||||
|
||||
let shutdown_pipe = File::open("/scheme/kernel.acpi/kstop")
|
||||
- .expect("acpid: failed to open `/scheme/kernel.acpi/kstop`");
|
||||
-
|
||||
- let mut event_queue = RawEventQueue::new().expect("acpid: failed to create event queue");
|
||||
- let socket = Socket::nonblock().expect("acpid: failed to create disk scheme");
|
||||
+ .unwrap_or_else(|err| {
|
||||
+ eprintln!("acpid: failed to open `/scheme/kernel.acpi/kstop`: {err}");
|
||||
+ process::exit(1);
|
||||
+ });
|
||||
+
|
||||
+ let mut event_queue = RawEventQueue::new().unwrap_or_else(|err| {
|
||||
+ eprintln!("acpid: failed to create event queue: {err}");
|
||||
+ process::exit(1);
|
||||
+ });
|
||||
+ let socket = Socket::nonblock().unwrap_or_else(|err| {
|
||||
+ eprintln!("acpid: failed to create disk scheme: {err}");
|
||||
+ process::exit(1);
|
||||
+ });
|
||||
|
||||
let mut scheme = self::scheme::AcpiScheme::new(&acpi_context, &socket);
|
||||
let mut handler = Blocking::new(&socket, 16);
|
||||
|
||||
event_queue
|
||||
.subscribe(shutdown_pipe.as_raw_fd() as usize, 0, EventFlags::READ)
|
||||
- .expect("acpid: failed to register shutdown pipe for event queue");
|
||||
+ .unwrap_or_else(|err| {
|
||||
+ eprintln!("acpid: failed to register shutdown pipe for event queue: {err}");
|
||||
+ process::exit(1);
|
||||
+ });
|
||||
event_queue
|
||||
.subscribe(socket.inner().raw(), 1, EventFlags::READ)
|
||||
- .expect("acpid: failed to register scheme socket for event queue");
|
||||
+ .unwrap_or_else(|err| {
|
||||
+ eprintln!("acpid: failed to register scheme socket for event queue: {err}");
|
||||
+ process::exit(1);
|
||||
+ });
|
||||
|
||||
register_sync_scheme(&socket, "acpi", &mut scheme)
|
||||
- .expect("acpid: failed to register acpi scheme to namespace");
|
||||
+ .unwrap_or_else(|err| {
|
||||
+ eprintln!("acpid: failed to register acpi scheme to namespace: {err}");
|
||||
+ process::exit(1);
|
||||
+ });
|
||||
|
||||
daemon.ready();
|
||||
|
||||
- libredox::call::setrens(0, 0).expect("acpid: failed to enter null namespace");
|
||||
+ libredox::call::setrens(0, 0).unwrap_or_else(|err| {
|
||||
+ eprintln!("acpid: failed to enter null namespace: {err}");
|
||||
+ process::exit(1);
|
||||
+ });
|
||||
|
||||
let mut mounted = true;
|
||||
while mounted {
|
||||
- let Some(event) = event_queue
|
||||
- .next()
|
||||
- .transpose()
|
||||
- .expect("acpid: failed to read event file")
|
||||
- else {
|
||||
+ let Some(event) = event_queue.next().transpose().unwrap_or_else(|err| {
|
||||
+ eprintln!("acpid: failed to read event file: {err}");
|
||||
+ process::exit(1);
|
||||
+ }) else {
|
||||
break;
|
||||
};
|
||||
|
||||
if event.fd == socket.inner().raw() {
|
||||
loop {
|
||||
- match handler
|
||||
- .process_requests_nonblocking(&mut scheme)
|
||||
- .expect("acpid: failed to process requests")
|
||||
- {
|
||||
+ match handler.process_requests_nonblocking(&mut scheme).unwrap_or_else(|err| {
|
||||
+ eprintln!("acpid: failed to process requests: {err}");
|
||||
+ process::exit(1);
|
||||
+ }) {
|
||||
ControlFlow::Continue(()) => {}
|
||||
ControlFlow::Break(()) => break,
|
||||
}
|
||||
@@ -134,7 +190,8 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
|
||||
acpi_context.set_global_s_state(5);
|
||||
|
||||
- unreachable!("System should have shut down before this is entered");
|
||||
+ eprintln!("acpid: system did not shut down after requesting S5");
|
||||
+ process::exit(1);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
diff --git a/drivers/pcid/src/main.rs b/drivers/pcid/src/main.rs
|
||||
index 61cd9a78..18ee18ab 100644
|
||||
--- a/drivers/pcid/src/main.rs
|
||||
+++ b/drivers/pcid/src/main.rs
|
||||
@@ -3,6 +3,7 @@
|
||||
#![feature(non_exhaustive_omitted_patterns_lint)]
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
+use std::process;
|
||||
|
||||
use log::{debug, info, trace, warn};
|
||||
use pci_types::capability::PciCapability;
|
||||
@@ -42,7 +43,16 @@ fn handle_parsed_header(
|
||||
continue;
|
||||
}
|
||||
match endpoint_header.bar(i, pcie) {
|
||||
- Some(TyBar::Io { port }) => bars[i as usize] = PciBar::Port(port.try_into().unwrap()),
|
||||
+ Some(TyBar::Io { port }) => match port.try_into() {
|
||||
+ Ok(port) => bars[i as usize] = PciBar::Port(port),
|
||||
+ Err(_) => {
|
||||
+ warn!(
|
||||
+ "pcid: skipping invalid I/O BAR port {port:#x} on {}",
|
||||
+ endpoint_header.header().address()
|
||||
+ );
|
||||
+ bars[i as usize] = PciBar::None;
|
||||
+ }
|
||||
+ },
|
||||
Some(TyBar::Memory32 {
|
||||
address,
|
||||
size,
|
||||
@@ -251,7 +261,10 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
info!("PCI SG-BS:DV.F VEND:DEVI CL.SC.IN.RV");
|
||||
|
||||
let mut scheme = scheme::PciScheme::new(pcie);
|
||||
- let socket = redox_scheme::Socket::create().expect("failed to open pci scheme socket");
|
||||
+ let socket = redox_scheme::Socket::create().unwrap_or_else(|err| {
|
||||
+ eprintln!("pcid: failed to open pci scheme socket: {err}");
|
||||
+ process::exit(1);
|
||||
+ });
|
||||
let handler = Blocking::new(&socket, 16);
|
||||
|
||||
{
|
||||
@@ -259,17 +272,27 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
Ok(register_pci) => {
|
||||
let access_id = scheme.access();
|
||||
|
||||
- let access_fd = socket
|
||||
- .create_this_scheme_fd(0, access_id, syscall::O_RDWR, 0)
|
||||
- .expect("failed to issue this resource");
|
||||
- let access_bytes = access_fd.to_ne_bytes();
|
||||
- let _ = register_pci
|
||||
- .call_wo(
|
||||
- &access_bytes,
|
||||
- syscall::CallFlags::WRITE | syscall::CallFlags::FD,
|
||||
- &[],
|
||||
- )
|
||||
- .expect("failed to send pci_fd to acpid");
|
||||
+ match socket.create_this_scheme_fd(0, access_id, syscall::O_RDWR, 0) {
|
||||
+ Ok(access_fd) => {
|
||||
+ let access_bytes = access_fd.to_ne_bytes();
|
||||
+ if let Err(err) = register_pci.call_wo(
|
||||
+ &access_bytes,
|
||||
+ syscall::CallFlags::WRITE | syscall::CallFlags::FD,
|
||||
+ &[],
|
||||
+ ) {
|
||||
+ warn!(
|
||||
+ "pcid: failed to send pci_fd to acpid (error: {}). Running without ACPI integration.",
|
||||
+ err
|
||||
+ );
|
||||
+ }
|
||||
+ }
|
||||
+ Err(err) => {
|
||||
+ warn!(
|
||||
+ "pcid: failed to issue acpid registration resource (error: {}). Running without ACPI integration.",
|
||||
+ err
|
||||
+ );
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
Err(err) => {
|
||||
if err.errno() == libredox::errno::ENODEV {
|
||||
@@ -305,13 +328,20 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
debug!("Enumeration complete, now starting pci scheme");
|
||||
|
||||
register_sync_scheme(&socket, "pci", &mut scheme)
|
||||
- .expect("failed to register pci scheme to namespace");
|
||||
+ .unwrap_or_else(|err| {
|
||||
+ eprintln!("pcid: failed to register pci scheme to namespace: {err}");
|
||||
+ process::exit(1);
|
||||
+ });
|
||||
|
||||
let _ = daemon.ready();
|
||||
|
||||
- handler
|
||||
- .process_requests_blocking(scheme)
|
||||
- .expect("pcid: failed to process requests");
|
||||
+ match handler.process_requests_blocking(scheme) {
|
||||
+ Ok(never) => match never {},
|
||||
+ Err(err) => {
|
||||
+ eprintln!("pcid: failed to process requests: {err}");
|
||||
+ process::exit(1);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
fn scan_device(
|
||||
@@ -323,6 +353,7 @@ fn scan_device(
|
||||
) {
|
||||
for func_num in 0..8 {
|
||||
let header = TyPciHeader::new(PciAddress::new(0, bus_num, dev_num, func_num));
|
||||
+ let header_address = header.address();
|
||||
|
||||
let (vendor_id, device_id) = header.id(pcie);
|
||||
if vendor_id == 0xffff && device_id == 0xffff {
|
||||
@@ -344,21 +375,40 @@ fn scan_device(
|
||||
revision,
|
||||
};
|
||||
|
||||
- info!("PCI {} {}", header.address(), full_device_id.display());
|
||||
+ info!("PCI {} {}", header_address, full_device_id.display());
|
||||
|
||||
let has_multiple_functions = header.has_multiple_functions(pcie);
|
||||
|
||||
match header.header_type(pcie) {
|
||||
HeaderType::Endpoint => {
|
||||
+ let endpoint_header = match EndpointHeader::from_header(header, pcie) {
|
||||
+ Some(endpoint_header) => endpoint_header,
|
||||
+ None => {
|
||||
+ warn!(
|
||||
+ "pcid: failed to parse endpoint header for {}",
|
||||
+ header_address,
|
||||
+ );
|
||||
+ continue;
|
||||
+ }
|
||||
+ };
|
||||
handle_parsed_header(
|
||||
pcie,
|
||||
tree,
|
||||
- EndpointHeader::from_header(header, pcie).unwrap(),
|
||||
+ endpoint_header,
|
||||
full_device_id,
|
||||
);
|
||||
}
|
||||
HeaderType::PciPciBridge => {
|
||||
- let bridge_header = PciPciBridgeHeader::from_header(header, pcie).unwrap();
|
||||
+ let bridge_header = match PciPciBridgeHeader::from_header(header, pcie) {
|
||||
+ Some(bridge_header) => bridge_header,
|
||||
+ None => {
|
||||
+ warn!(
|
||||
+ "pcid: failed to parse bridge header for {}",
|
||||
+ header_address,
|
||||
+ );
|
||||
+ continue;
|
||||
+ }
|
||||
+ };
|
||||
bus_nums.push(bridge_header.secondary_bus_number(pcie));
|
||||
}
|
||||
ty => {
|
||||
diff --git a/init/src/main.rs b/init/src/main.rs
|
||||
index 5682cf44..cd270a6e 100644
|
||||
--- a/init/src/main.rs
|
||||
+++ b/init/src/main.rs
|
||||
@@ -1,6 +1,7 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::ffi::OsString;
|
||||
use std::path::Path;
|
||||
+use std::time::Duration;
|
||||
use std::{env, fs, io};
|
||||
|
||||
use libredox::flag::{O_RDONLY, O_WRONLY};
|
||||
@@ -166,19 +167,36 @@ fn main() {
|
||||
}
|
||||
};
|
||||
for entry in entries {
|
||||
+ let Some(unit_name) = entry.file_name().and_then(|name| name.to_str()) else {
|
||||
+ eprintln!(
|
||||
+ "init: skipping config entry with invalid filename: {}",
|
||||
+ entry.display()
|
||||
+ );
|
||||
+ continue;
|
||||
+ };
|
||||
scheduler.schedule_start_and_report_errors(
|
||||
&mut unit_store,
|
||||
- UnitId(entry.file_name().unwrap().to_str().unwrap().to_owned()),
|
||||
+ UnitId(unit_name.to_owned()),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
scheduler.step(&mut unit_store, &mut init_config);
|
||||
|
||||
- libredox::call::setrens(0, 0).expect("init: failed to enter null namespace");
|
||||
+ if let Err(err) = libredox::call::setrens(0, 0) {
|
||||
+ eprintln!("init: failed to enter null namespace: {err}");
|
||||
+ std::process::exit(1);
|
||||
+ }
|
||||
|
||||
loop {
|
||||
let mut status = 0;
|
||||
- libredox::call::waitpid(0, &mut status, 0).unwrap();
|
||||
+ match libredox::call::waitpid(0, &mut status, 0) {
|
||||
+ Ok(_) => {}
|
||||
+ Err(err) if err.errno() == libredox::errno::EINTR => continue,
|
||||
+ Err(err) => {
|
||||
+ eprintln!("init: waitpid failed: {err}");
|
||||
+ std::thread::sleep(Duration::from_millis(100));
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
}
|
||||
diff --git a/init/src/scheduler.rs b/init/src/scheduler.rs
|
||||
index d42a4e57..3b8d10b0 100644
|
||||
--- a/init/src/scheduler.rs
|
||||
+++ b/init/src/scheduler.rs
|
||||
@@ -43,7 +43,10 @@ impl Scheduler {
|
||||
) {
|
||||
let loaded_units = unit_store.load_units(unit_id.clone(), errors);
|
||||
for unit_id in loaded_units {
|
||||
- if !unit_store.unit(&unit_id).conditions_met() {
|
||||
+ if unit_store
|
||||
+ .try_unit(&unit_id)
|
||||
+ .is_ok_and(|unit| !unit.conditions_met())
|
||||
+ {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -62,7 +65,10 @@ impl Scheduler {
|
||||
|
||||
match job.kind {
|
||||
JobKind::Start => {
|
||||
- let unit = unit_store.unit_mut(&job.unit);
|
||||
+ let Ok(unit) = unit_store.try_unit_mut(&job.unit) else {
|
||||
+ eprintln!("init: unit {} not found in store, skipping", job.unit.0);
|
||||
+ continue 'a;
|
||||
+ };
|
||||
|
||||
for dep in &unit.info.requires_weak {
|
||||
for pending_job in &self.pending {
|
||||
diff --git a/init/src/service.rs b/init/src/service.rs
|
||||
index ed0023e9..827ae275 100644
|
||||
--- a/init/src/service.rs
|
||||
+++ b/init/src/service.rs
|
||||
@@ -3,13 +3,24 @@ use std::ffi::OsString;
|
||||
use std::io::Read;
|
||||
use std::os::fd::{AsRawFd, OwnedFd};
|
||||
use std::os::unix::process::CommandExt;
|
||||
-use std::process::Command;
|
||||
+use std::process::{Child, Command};
|
||||
use std::{env, io};
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::script::subst_env;
|
||||
|
||||
+fn terminate_child(child: &mut Child, command: &str) {
|
||||
+ if let Err(err) = child.kill() {
|
||||
+ if err.kind() != io::ErrorKind::InvalidInput {
|
||||
+ eprintln!("init: failed to terminate {command}: {err}");
|
||||
+ }
|
||||
+ }
|
||||
+ if let Err(err) = child.wait() {
|
||||
+ eprintln!("init: failed to reap {command}: {err}");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Service {
|
||||
@@ -37,7 +48,8 @@ pub enum ServiceType {
|
||||
impl Service {
|
||||
pub fn spawn(&self, base_envs: &BTreeMap<String, OsString>) {
|
||||
let mut command = Command::new(&self.cmd);
|
||||
- command.args(self.args.iter().map(|arg| subst_env(arg)));
|
||||
+ let resolved_args: Vec<String> = self.args.iter().map(|arg| subst_env(arg)).collect();
|
||||
+ command.args(&resolved_args);
|
||||
command.env_clear();
|
||||
for env in &self.inherit_envs {
|
||||
if let Some(value) = env::var_os(env) {
|
||||
@@ -45,14 +57,25 @@ impl Service {
|
||||
}
|
||||
}
|
||||
command.envs(base_envs).envs(&self.envs);
|
||||
+ let command_display = if resolved_args.is_empty() {
|
||||
+ self.cmd.clone()
|
||||
+ } else {
|
||||
+ format!("{} {}", self.cmd, resolved_args.join(" "))
|
||||
+ };
|
||||
|
||||
- let (mut read_pipe, write_pipe) = io::pipe().unwrap();
|
||||
+ let (mut read_pipe, write_pipe) = match io::pipe().map_err(|err| {
|
||||
+ eprintln!("init: failed to create readiness pipe for {command_display}: {err}");
|
||||
+ err
|
||||
+ }) {
|
||||
+ Ok(pair) => pair,
|
||||
+ Err(_) => return,
|
||||
+ };
|
||||
unsafe { pass_fd(&mut command, "INIT_NOTIFY", write_pipe.into()) };
|
||||
|
||||
let mut child = match command.spawn() {
|
||||
Ok(child) => child,
|
||||
Err(err) => {
|
||||
- eprintln!("init: failed to execute {:?}: {}", command, err);
|
||||
+ eprintln!("init: failed to execute {command_display}: {err}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -61,10 +84,10 @@ impl Service {
|
||||
ServiceType::Notify => match read_pipe.read_exact(&mut [0]) {
|
||||
Ok(()) => {}
|
||||
Err(err) if err.kind() == io::ErrorKind::UnexpectedEof => {
|
||||
- eprintln!("init: {command:?} exited without notifying readiness");
|
||||
+ eprintln!("init: {command_display} exited without notifying readiness");
|
||||
}
|
||||
Err(err) => {
|
||||
- eprintln!("init: failed to wait for {command:?}: {err}");
|
||||
+ eprintln!("init: failed to wait for {command_display}: {err}");
|
||||
}
|
||||
},
|
||||
ServiceType::Scheme(scheme) => {
|
||||
@@ -80,7 +103,7 @@ impl Service {
|
||||
errno: syscall::EINTR,
|
||||
}) => continue,
|
||||
Ok(0) => {
|
||||
- eprintln!("init: {command:?} exited without notifying readiness");
|
||||
+ eprintln!("init: {command_display} exited without notifying readiness");
|
||||
return;
|
||||
}
|
||||
Ok(1) => break,
|
||||
@@ -89,26 +112,40 @@ impl Service {
|
||||
return;
|
||||
}
|
||||
Err(err) => {
|
||||
- eprintln!("init: failed to wait for {command:?}: {err}");
|
||||
+ eprintln!("init: failed to wait for {command_display}: {err}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- let current_namespace_fd = libredox::call::getns().expect("TODO");
|
||||
- libredox::call::register_scheme_to_ns(current_namespace_fd, scheme, new_fd)
|
||||
- .expect("TODO");
|
||||
+ let current_namespace_fd = match libredox::call::getns() {
|
||||
+ Ok(fd) => fd,
|
||||
+ Err(err) => {
|
||||
+ eprintln!("init: failed to get current namespace for {command_display}: {err}");
|
||||
+ terminate_child(&mut child, &command_display);
|
||||
+ return;
|
||||
+ }
|
||||
+ };
|
||||
+ if let Err(err) =
|
||||
+ libredox::call::register_scheme_to_ns(current_namespace_fd, scheme, new_fd)
|
||||
+ {
|
||||
+ eprintln!(
|
||||
+ "init: failed to register scheme {scheme:?} for {command_display}: {err}"
|
||||
+ );
|
||||
+ terminate_child(&mut child, &command_display);
|
||||
+ return;
|
||||
+ }
|
||||
}
|
||||
ServiceType::Oneshot => {
|
||||
drop(read_pipe);
|
||||
match child.wait() {
|
||||
Ok(exit_status) => {
|
||||
if !exit_status.success() {
|
||||
- eprintln!("init: {command:?} failed with {exit_status}");
|
||||
+ eprintln!("init: {command_display} failed with {exit_status}");
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
- eprintln!("init: failed to wait for {:?}: {}", command, err)
|
||||
+ eprintln!("init: failed to wait for {command_display}: {err}")
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/init/src/unit.rs b/init/src/unit.rs
|
||||
index 98053cb2..bd998394 100644
|
||||
--- a/init/src/unit.rs
|
||||
+++ b/init/src/unit.rs
|
||||
@@ -23,8 +23,14 @@ impl UnitStore {
|
||||
}
|
||||
|
||||
pub fn set_runtime_target(&mut self, unit_id: UnitId) {
|
||||
- assert!(self.runtime_target.is_none());
|
||||
- assert!(self.units.contains_key(&unit_id));
|
||||
+ if self.runtime_target.is_some() {
|
||||
+ eprintln!("init: runtime target already set, ignoring {}", unit_id.0);
|
||||
+ return;
|
||||
+ }
|
||||
+ if !self.units.contains_key(&unit_id) {
|
||||
+ eprintln!("init: runtime target {} not found in unit store", unit_id.0);
|
||||
+ return;
|
||||
+ }
|
||||
self.runtime_target = Some(unit_id);
|
||||
}
|
||||
|
||||
@@ -85,8 +91,15 @@ impl UnitStore {
|
||||
let unit = self.load_single_unit(unit_id, errors);
|
||||
if let Some(unit) = unit {
|
||||
loaded_units.push(unit.clone());
|
||||
- for dep in &self.unit(&unit).info.requires_weak {
|
||||
- pending_units.push(dep.clone());
|
||||
+ match self.try_unit(&unit) {
|
||||
+ Ok(unit) => {
|
||||
+ for dep in &unit.info.requires_weak {
|
||||
+ pending_units.push(dep.clone());
|
||||
+ }
|
||||
+ }
|
||||
+ Err(err) => {
|
||||
+ errors.push(err);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,12 +107,34 @@ impl UnitStore {
|
||||
loaded_units
|
||||
}
|
||||
|
||||
+ pub fn try_unit(&self, unit: &UnitId) -> Result<&Unit, String> {
|
||||
+ self.units
|
||||
+ .get(unit)
|
||||
+ .ok_or_else(|| format!("unit {} not found in store", unit.0))
|
||||
+ }
|
||||
+
|
||||
+ // Keep the legacy infallible accessors for compatibility while scheduler/load paths
|
||||
+ // use the fallible helpers to avoid panicking on missing units.
|
||||
+ #[allow(dead_code)]
|
||||
pub fn unit(&self, unit: &UnitId) -> &Unit {
|
||||
- self.units.get(unit).unwrap()
|
||||
+ self.try_unit(unit).unwrap_or_else(|err| {
|
||||
+ eprintln!("init: {err}");
|
||||
+ std::process::exit(1);
|
||||
+ })
|
||||
+ }
|
||||
+
|
||||
+ pub fn try_unit_mut(&mut self, unit: &UnitId) -> Result<&mut Unit, String> {
|
||||
+ self.units
|
||||
+ .get_mut(unit)
|
||||
+ .ok_or_else(|| format!("unit {} not found in store", unit.0))
|
||||
}
|
||||
|
||||
+ #[allow(dead_code)]
|
||||
pub fn unit_mut(&mut self, unit: &UnitId) -> &mut Unit {
|
||||
- self.units.get_mut(unit).unwrap()
|
||||
+ self.try_unit_mut(unit).unwrap_or_else(|err| {
|
||||
+ eprintln!("init: {err}");
|
||||
+ std::process::exit(1);
|
||||
+ })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,7 +215,7 @@ impl Unit {
|
||||
) -> io::Result<Self> {
|
||||
let config = fs::read_to_string(config_path)?;
|
||||
|
||||
- let Some(ext) = config_path.extension().map(|ext| ext.to_str().unwrap()) else {
|
||||
+ let Some(ext) = config_path.extension().and_then(|ext| ext.to_str()) else {
|
||||
let script = Script::from_str(&config, errors)?;
|
||||
return Ok(Unit {
|
||||
id,
|
||||
@@ -0,0 +1,633 @@
|
||||
diff --git a/drivers/acpid/src/acpi.rs b/drivers/acpid/src/acpi.rs
|
||||
index 94a1eb17e..3521bfc7b 100644
|
||||
--- a/drivers/acpid/src/acpi.rs
|
||||
+++ b/drivers/acpid/src/acpi.rs
|
||||
@@ -136,9 +136,10 @@ impl Sdt {
|
||||
let header = match plain::from_bytes::<SdtHeader>(&slice) {
|
||||
Ok(header) => header,
|
||||
Err(plain::Error::TooShort) => return Err(InvalidSdtError::InvalidSize),
|
||||
- Err(plain::Error::BadAlignment) => panic!(
|
||||
- "plain::from_bytes failed due to alignment, but SdtHeader is #[repr(packed)]!"
|
||||
- ),
|
||||
+ Err(plain::Error::BadAlignment) => {
|
||||
+ log::error!("acpid: plain::from_bytes failed due to alignment, but SdtHeader is #[repr(packed)] - internal inconsistency");
|
||||
+ return Err(InvalidSdtError::InvalidSize);
|
||||
+ }
|
||||
};
|
||||
|
||||
if header.length() != slice.len() {
|
||||
diff --git a/drivers/acpid/src/main.rs b/drivers/acpid/src/main.rs
|
||||
index 059254b3e..8f99f2ea9 100644
|
||||
--- a/drivers/acpid/src/main.rs
|
||||
+++ b/drivers/acpid/src/main.rs
|
||||
@@ -28,9 +28,13 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
|
||||
log::info!("acpid start");
|
||||
|
||||
- let rxsdt_raw_data: Arc<[u8]> = std::fs::read("/scheme/kernel.acpi/rxsdt")
|
||||
- .expect("acpid: failed to read `/scheme/kernel.acpi/rxsdt`")
|
||||
- .into();
|
||||
+ let rxsdt_raw_data: Arc<[u8]> = match std::fs::read("/scheme/kernel.acpi/rxsdt") {
|
||||
+ Ok(data) => data.into(),
|
||||
+ Err(err) => {
|
||||
+ log::error!("acpid: failed to read `/scheme/kernel.acpi/rxsdt`: {}", err);
|
||||
+ std::process::exit(1);
|
||||
+ }
|
||||
+ };
|
||||
|
||||
if rxsdt_raw_data.is_empty() {
|
||||
log::info!("System doesn't use ACPI");
|
||||
@@ -38,7 +42,13 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
- let sdt = self::acpi::Sdt::new(rxsdt_raw_data).expect("acpid: failed to parse [RX]SDT");
|
||||
+ let sdt = match self::acpi::Sdt::new(rxsdt_raw_data) {
|
||||
+ Ok(sdt) => sdt,
|
||||
+ Err(err) => {
|
||||
+ log::error!("acpid: failed to parse [RX]SDT: {:?}", err);
|
||||
+ std::process::exit(1);
|
||||
+ }
|
||||
+ };
|
||||
|
||||
let mut thirty_two_bit;
|
||||
let mut sixty_four_bit;
|
||||
@@ -64,7 +74,10 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
|
||||
&mut sixty_four_bit as &mut dyn Iterator<Item = u64>
|
||||
}
|
||||
- _ => panic!("acpid: expected [RX]SDT from kernel to be either of those"),
|
||||
+ _ => {
|
||||
+ log::error!("acpid: expected [RX]SDT from kernel to be RSDT or XSDT");
|
||||
+ std::process::exit(1);
|
||||
+ }
|
||||
};
|
||||
|
||||
let region_handlers: Vec<(RegionSpace, Box<dyn RegionHandler + 'static>)> = vec![
|
||||
@@ -75,49 +88,84 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
|
||||
// TODO: I/O permission bitmap?
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
- common::acquire_port_io_rights().expect("acpid: failed to set I/O privilege level to Ring 3");
|
||||
+ if let Err(err) = common::acquire_port_io_rights() {
|
||||
+ log::error!("acpid: failed to set I/O privilege level to Ring 3: {:?}", err);
|
||||
+ std::process::exit(1);
|
||||
+ }
|
||||
|
||||
- let shutdown_pipe = File::open("/scheme/kernel.acpi/kstop")
|
||||
- .expect("acpid: failed to open `/scheme/kernel.acpi/kstop`");
|
||||
+ let shutdown_pipe = match File::open("/scheme/kernel.acpi/kstop") {
|
||||
+ Ok(f) => f,
|
||||
+ Err(err) => {
|
||||
+ log::error!("acpid: failed to open `/scheme/kernel.acpi/kstop`: {}", err);
|
||||
+ std::process::exit(1);
|
||||
+ }
|
||||
+ };
|
||||
|
||||
- let mut event_queue = RawEventQueue::new().expect("acpid: failed to create event queue");
|
||||
- let socket = Socket::nonblock().expect("acpid: failed to create disk scheme");
|
||||
+ let mut event_queue = match RawEventQueue::new() {
|
||||
+ Ok(q) => q,
|
||||
+ Err(err) => {
|
||||
+ log::error!("acpid: failed to create event queue: {:?}", err);
|
||||
+ std::process::exit(1);
|
||||
+ }
|
||||
+ };
|
||||
+ let socket = match Socket::nonblock() {
|
||||
+ Ok(s) => s,
|
||||
+ Err(err) => {
|
||||
+ log::error!("acpid: failed to create scheme socket: {:?}", err);
|
||||
+ std::process::exit(1);
|
||||
+ }
|
||||
+ };
|
||||
|
||||
let mut scheme = self::scheme::AcpiScheme::new(&acpi_context, &socket);
|
||||
let mut handler = Blocking::new(&socket, 16);
|
||||
|
||||
- event_queue
|
||||
+ if let Err(err) = event_queue
|
||||
.subscribe(shutdown_pipe.as_raw_fd() as usize, 0, EventFlags::READ)
|
||||
- .expect("acpid: failed to register shutdown pipe for event queue");
|
||||
- event_queue
|
||||
+ {
|
||||
+ log::error!("acpid: failed to register shutdown pipe for event queue: {:?}", err);
|
||||
+ std::process::exit(1);
|
||||
+ }
|
||||
+ if let Err(err) = event_queue
|
||||
.subscribe(socket.inner().raw(), 1, EventFlags::READ)
|
||||
- .expect("acpid: failed to register scheme socket for event queue");
|
||||
+ {
|
||||
+ log::error!("acpid: failed to register scheme socket for event queue: {:?}", err);
|
||||
+ std::process::exit(1);
|
||||
+ }
|
||||
|
||||
- register_sync_scheme(&socket, "acpi", &mut scheme)
|
||||
- .expect("acpid: failed to register acpi scheme to namespace");
|
||||
+ if let Err(err) = register_sync_scheme(&socket, "acpi", &mut scheme) {
|
||||
+ log::error!("acpid: failed to register acpi scheme to namespace: {:?}", err);
|
||||
+ std::process::exit(1);
|
||||
+ }
|
||||
|
||||
daemon.ready();
|
||||
|
||||
- libredox::call::setrens(0, 0).expect("acpid: failed to enter null namespace");
|
||||
+ if let Err(err) = libredox::call::setrens(0, 0) {
|
||||
+ log::error!("acpid: failed to enter null namespace: {}", err);
|
||||
+ std::process::exit(1);
|
||||
+ }
|
||||
|
||||
let mut mounted = true;
|
||||
while mounted {
|
||||
- let Some(event) = event_queue
|
||||
- .next()
|
||||
- .transpose()
|
||||
- .expect("acpid: failed to read event file")
|
||||
- else {
|
||||
- break;
|
||||
+ let event = match event_queue.next().transpose() {
|
||||
+ Ok(Some(ev)) => ev,
|
||||
+ Ok(None) => break,
|
||||
+ Err(err) => {
|
||||
+ log::error!("acpid: failed to read event file: {:?}", err);
|
||||
+ break;
|
||||
+ }
|
||||
};
|
||||
|
||||
if event.fd == socket.inner().raw() {
|
||||
loop {
|
||||
- match handler
|
||||
- .process_requests_nonblocking(&mut scheme)
|
||||
- .expect("acpid: failed to process requests")
|
||||
- {
|
||||
- ControlFlow::Continue(()) => {}
|
||||
- ControlFlow::Break(()) => break,
|
||||
+ match handler.process_requests_nonblocking(&mut scheme) {
|
||||
+ Ok(flow) => match flow {
|
||||
+ ControlFlow::Continue(()) => {}
|
||||
+ ControlFlow::Break(()) => break,
|
||||
+ },
|
||||
+ Err(err) => {
|
||||
+ log::error!("acpid: failed to process requests: {:?}", err);
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
} else if event.fd == shutdown_pipe.as_raw_fd() as usize {
|
||||
diff --git a/drivers/pcid/src/main.rs b/drivers/pcid/src/main.rs
|
||||
index 61cd9a787..cad33114b 100644
|
||||
--- a/drivers/pcid/src/main.rs
|
||||
+++ b/drivers/pcid/src/main.rs
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
-use log::{debug, info, trace, warn};
|
||||
+use log::{debug, error, info, trace, warn};
|
||||
use pci_types::capability::PciCapability;
|
||||
use pci_types::{
|
||||
Bar as TyBar, CommandRegister, EndpointHeader, HeaderType, PciAddress,
|
||||
@@ -259,17 +259,25 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
Ok(register_pci) => {
|
||||
let access_id = scheme.access();
|
||||
|
||||
- let access_fd = socket
|
||||
+ let access_fd = match socket
|
||||
.create_this_scheme_fd(0, access_id, syscall::O_RDWR, 0)
|
||||
- .expect("failed to issue this resource");
|
||||
- let access_bytes = access_fd.to_ne_bytes();
|
||||
- let _ = register_pci
|
||||
- .call_wo(
|
||||
+ {
|
||||
+ Ok(fd) => Some(fd),
|
||||
+ Err(err) => {
|
||||
+ warn!("pcid: failed to issue acpi resource fd: {:?}", err);
|
||||
+ None
|
||||
+ }
|
||||
+ };
|
||||
+ if let Some(access_fd) = access_fd {
|
||||
+ let access_bytes = access_fd.to_ne_bytes();
|
||||
+ if let Err(err) = register_pci.call_wo(
|
||||
&access_bytes,
|
||||
syscall::CallFlags::WRITE | syscall::CallFlags::FD,
|
||||
&[],
|
||||
- )
|
||||
- .expect("failed to send pci_fd to acpid");
|
||||
+ ) {
|
||||
+ warn!("pcid: failed to send pci_fd to acpid: {:?}", err);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
Err(err) => {
|
||||
if err.errno() == libredox::errno::ENODEV {
|
||||
@@ -304,14 +312,17 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
}
|
||||
debug!("Enumeration complete, now starting pci scheme");
|
||||
|
||||
- register_sync_scheme(&socket, "pci", &mut scheme)
|
||||
- .expect("failed to register pci scheme to namespace");
|
||||
+ if let Err(err) = register_sync_scheme(&socket, "pci", &mut scheme) {
|
||||
+ error!("pcid: failed to register pci scheme to namespace: {:?}", err);
|
||||
+ std::process::exit(1);
|
||||
+ }
|
||||
|
||||
let _ = daemon.ready();
|
||||
|
||||
- handler
|
||||
- .process_requests_blocking(scheme)
|
||||
- .expect("pcid: failed to process requests");
|
||||
+ handler.process_requests_blocking(scheme).unwrap_or_else(|err| {
|
||||
+ error!("pcid: failed to process requests: {:?}", err);
|
||||
+ std::process::exit(1);
|
||||
+ });
|
||||
}
|
||||
|
||||
fn scan_device(
|
||||
diff --git a/init/src/main.rs b/init/src/main.rs
|
||||
index 5682cf445..72c97f53c 100644
|
||||
--- a/init/src/main.rs
|
||||
+++ b/init/src/main.rs
|
||||
@@ -166,19 +166,29 @@ fn main() {
|
||||
}
|
||||
};
|
||||
for entry in entries {
|
||||
+ let Some(file_name) = entry.file_name().and_then(|n| n.to_str()) else {
|
||||
+ eprintln!("init: skipping entry with invalid filename: {}", entry.display());
|
||||
+ continue;
|
||||
+ };
|
||||
scheduler.schedule_start_and_report_errors(
|
||||
&mut unit_store,
|
||||
- UnitId(entry.file_name().unwrap().to_str().unwrap().to_owned()),
|
||||
+ UnitId(file_name.to_owned()),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
scheduler.step(&mut unit_store, &mut init_config);
|
||||
|
||||
- libredox::call::setrens(0, 0).expect("init: failed to enter null namespace");
|
||||
+ if let Err(err) = libredox::call::setrens(0, 0) {
|
||||
+ eprintln!("init: failed to enter null namespace: {}", err);
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
loop {
|
||||
let mut status = 0;
|
||||
- libredox::call::waitpid(0, &mut status, 0).unwrap();
|
||||
+ match libredox::call::waitpid(0, &mut status, 0) {
|
||||
+ Ok(()) => {}
|
||||
+ Err(err) => eprintln!("init: waitpid error: {}", err),
|
||||
+ }
|
||||
}
|
||||
}
|
||||
diff --git a/init/src/scheduler.rs b/init/src/scheduler.rs
|
||||
index d42a4e570..333e0e20e 100644
|
||||
--- a/init/src/scheduler.rs
|
||||
+++ b/init/src/scheduler.rs
|
||||
@@ -1,7 +1,16 @@
|
||||
use std::collections::VecDeque;
|
||||
+use std::io::Read;
|
||||
+use std::os::fd::AsRawFd;
|
||||
+use std::os::unix::process::CommandExt;
|
||||
+use std::process::Command;
|
||||
+use std::time::Duration;
|
||||
+use std::{env, io};
|
||||
|
||||
use crate::InitConfig;
|
||||
-use crate::unit::{Unit, UnitId, UnitKind, UnitStore};
|
||||
+use crate::service::ServiceType;
|
||||
+use crate::unit::{RestartPolicy, UnitId, UnitKind, UnitStore};
|
||||
+
|
||||
+const MAX_DEPENDENCY_WAIT_RETRIES: u32 = 1000;
|
||||
|
||||
pub struct Scheduler {
|
||||
pending: VecDeque<Job>,
|
||||
@@ -10,10 +19,12 @@ pub struct Scheduler {
|
||||
struct Job {
|
||||
unit: UnitId,
|
||||
kind: JobKind,
|
||||
+ dep_retries: u32,
|
||||
}
|
||||
|
||||
enum JobKind {
|
||||
Start,
|
||||
+ Restart { backoff: Duration },
|
||||
}
|
||||
|
||||
impl Scheduler {
|
||||
@@ -50,37 +61,97 @@ impl Scheduler {
|
||||
self.pending.push_back(Job {
|
||||
unit: unit_id,
|
||||
kind: JobKind::Start,
|
||||
+ dep_retries: 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn step(&mut self, unit_store: &mut UnitStore, init_config: &mut InitConfig) {
|
||||
'a: loop {
|
||||
- let Some(job) = self.pending.pop_front() else {
|
||||
+ let Some(mut job) = self.pending.pop_front() else {
|
||||
return;
|
||||
};
|
||||
|
||||
match job.kind {
|
||||
JobKind::Start => {
|
||||
- let unit = unit_store.unit_mut(&job.unit);
|
||||
+ let unit = unit_store.unit(&job.unit);
|
||||
|
||||
+ let timeout_secs = unit.info.dependency_timeout_secs;
|
||||
+ let mut deps_pending = false;
|
||||
for dep in &unit.info.requires_weak {
|
||||
for pending_job in &self.pending {
|
||||
if &pending_job.unit == dep {
|
||||
- self.pending.push_back(job);
|
||||
- continue 'a;
|
||||
+ deps_pending = true;
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
+ if deps_pending {
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
|
||||
- run(unit, init_config);
|
||||
+ if deps_pending {
|
||||
+ if timeout_secs > 0 {
|
||||
+ job.dep_retries += 1;
|
||||
+ let max_retries = timeout_secs * 100; // ~10ms per retry
|
||||
+ if job.dep_retries > max_retries as u32 {
|
||||
+ eprintln!(
|
||||
+ "init: {}: dependency timeout after {}s, failing",
|
||||
+ job.unit.0, timeout_secs
|
||||
+ );
|
||||
+ continue;
|
||||
+ }
|
||||
+ } else if job.dep_retries >= MAX_DEPENDENCY_WAIT_RETRIES {
|
||||
+ eprintln!(
|
||||
+ "init: {}: dependency wait exceeded {} retries, failing",
|
||||
+ job.unit.0, MAX_DEPENDENCY_WAIT_RETRIES
|
||||
+ );
|
||||
+ continue;
|
||||
+ }
|
||||
+ job.dep_retries += 1;
|
||||
+ self.pending.push_back(job);
|
||||
+ continue 'a;
|
||||
+ }
|
||||
+
|
||||
+ if let Err(restart) = run(unit_store, &job.unit, init_config) {
|
||||
+ if let Some(backoff) = restart {
|
||||
+ self.pending.push_back(Job {
|
||||
+ unit: job.unit.clone(),
|
||||
+ kind: JobKind::Restart { backoff },
|
||||
+ dep_retries: 0,
|
||||
+ });
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ JobKind::Restart { backoff } => {
|
||||
+ std::thread::sleep(backoff);
|
||||
+ let next_backoff = (backoff * 2).min(Duration::from_secs(60));
|
||||
+ if let Err(restart) = run(unit_store, &job.unit, init_config) {
|
||||
+ if let Some(_next) = restart {
|
||||
+ self.pending.push_back(Job {
|
||||
+ unit: job.unit,
|
||||
+ kind: JobKind::Restart {
|
||||
+ backoff: next_backoff,
|
||||
+ },
|
||||
+ dep_retries: 0,
|
||||
+ });
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-fn run(unit: &mut Unit, config: &mut InitConfig) {
|
||||
+fn run(
|
||||
+ unit_store: &UnitStore,
|
||||
+ unit_id: &UnitId,
|
||||
+ config: &mut InitConfig,
|
||||
+) -> Result<(), Option<Duration>> {
|
||||
+ let unit = unit_store.unit(unit_id);
|
||||
+
|
||||
+ let restart_policy = unit.info.restart;
|
||||
+
|
||||
match &unit.kind {
|
||||
UnitKind::LegacyScript { script } => {
|
||||
for cmd in script.clone() {
|
||||
@@ -89,11 +160,12 @@ fn run(unit: &mut Unit, config: &mut InitConfig) {
|
||||
}
|
||||
cmd.run(config);
|
||||
}
|
||||
+ Ok(())
|
||||
}
|
||||
UnitKind::Service { service } => {
|
||||
if config.skip_cmd.contains(&service.cmd) {
|
||||
eprintln!("Skipping '{} {}'", service.cmd, service.args.join(" "));
|
||||
- return;
|
||||
+ return Ok(());
|
||||
}
|
||||
if config.log_debug {
|
||||
eprintln!(
|
||||
@@ -102,7 +174,44 @@ fn run(unit: &mut Unit, config: &mut InitConfig) {
|
||||
service.cmd,
|
||||
);
|
||||
}
|
||||
- service.spawn(&config.envs);
|
||||
+
|
||||
+ let mut command = Command::new(&service.cmd);
|
||||
+ command.args(&service.args);
|
||||
+ command.env_clear();
|
||||
+ for env in &service.inherit_envs {
|
||||
+ if let Some(value) = env::var_os(env) {
|
||||
+ command.env(env, value);
|
||||
+ }
|
||||
+ }
|
||||
+ command.envs(config.envs.iter().map(|(k, v)| (k.as_str(), v.as_os_str())));
|
||||
+
|
||||
+ let (read_pipe, write_pipe) = match io::pipe() {
|
||||
+ Ok(p) => p,
|
||||
+ Err(err) => {
|
||||
+ eprintln!("init: pipe failed for {}: {}", service.cmd, err);
|
||||
+ return Err(restart_signal(restart_policy));
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ let write_fd: std::os::fd::OwnedFd = write_pipe.into();
|
||||
+ unsafe {
|
||||
+ command.env("INIT_NOTIFY", format!("{}", write_fd.as_raw_fd()));
|
||||
+ command.pre_exec(move || {
|
||||
+ if unsafe { libc::fcntl(write_fd.as_raw_fd(), libc::F_SETFD, 0) } == -1 {
|
||||
+ Err(io::Error::last_os_error())
|
||||
+ } else {
|
||||
+ Ok(())
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
+ let status = service_spawn_status(read_pipe, command, &service.type_, &service.cmd);
|
||||
+
|
||||
+ match status {
|
||||
+ SpawnStatus::Success => Ok(()),
|
||||
+ SpawnStatus::Failed => Err(restart_signal(restart_policy)),
|
||||
+ SpawnStatus::Async => Ok(()),
|
||||
+ }
|
||||
}
|
||||
UnitKind::Target {} => {
|
||||
if config.log_debug {
|
||||
@@ -111,6 +220,113 @@ fn run(unit: &mut Unit, config: &mut InitConfig) {
|
||||
unit.info.description.as_ref().unwrap_or(&unit.id.0),
|
||||
);
|
||||
}
|
||||
+ Ok(())
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+enum SpawnStatus {
|
||||
+ Success,
|
||||
+ Failed,
|
||||
+ Async,
|
||||
+}
|
||||
+
|
||||
+fn restart_signal(policy: RestartPolicy) -> Option<Duration> {
|
||||
+ match policy {
|
||||
+ RestartPolicy::No => None,
|
||||
+ RestartPolicy::OnFailure | RestartPolicy::Always => Some(Duration::from_secs(1)),
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+fn service_spawn_status(
|
||||
+ mut read_pipe: impl Read + AsRawFd,
|
||||
+ mut command: Command,
|
||||
+ service_type: &ServiceType,
|
||||
+ cmd: &str,
|
||||
+) -> SpawnStatus {
|
||||
+ let mut child = match command.spawn() {
|
||||
+ Ok(child) => child,
|
||||
+ Err(err) => {
|
||||
+ eprintln!("init: failed to execute {}: {}", cmd, err);
|
||||
+ return SpawnStatus::Failed;
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ match service_type {
|
||||
+ ServiceType::Notify => match read_pipe.read_exact(&mut [0]) {
|
||||
+ Ok(()) => SpawnStatus::Success,
|
||||
+ Err(err) if err.kind() == io::ErrorKind::UnexpectedEof => {
|
||||
+ eprintln!("init: {cmd} exited without notifying readiness");
|
||||
+ SpawnStatus::Failed
|
||||
+ }
|
||||
+ Err(err) => {
|
||||
+ eprintln!("init: failed to wait for {cmd}: {err}");
|
||||
+ SpawnStatus::Failed
|
||||
+ }
|
||||
+ },
|
||||
+ ServiceType::Scheme(scheme) => {
|
||||
+ let scheme = scheme.clone();
|
||||
+ let mut new_fd = usize::MAX;
|
||||
+ let res = loop {
|
||||
+ match syscall::call_ro(
|
||||
+ read_pipe.as_raw_fd() as usize,
|
||||
+ unsafe { plain::as_mut_bytes(&mut new_fd) },
|
||||
+ syscall::CallFlags::FD | syscall::CallFlags::FD_UPPER,
|
||||
+ &[],
|
||||
+ ) {
|
||||
+ Err(syscall::Error {
|
||||
+ errno: syscall::EINTR,
|
||||
+ }) => continue,
|
||||
+ Ok(0) => break SpawnStatus::Failed,
|
||||
+ Ok(1) => break SpawnStatus::Success,
|
||||
+ Ok(n) => {
|
||||
+ eprintln!("init: incorrect amount of fds {n} returned from {cmd}");
|
||||
+ break SpawnStatus::Failed;
|
||||
+ }
|
||||
+ Err(err) => {
|
||||
+ eprintln!("init: failed to wait for {cmd}: {err}");
|
||||
+ break SpawnStatus::Failed;
|
||||
+ }
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ if matches!(res, SpawnStatus::Success) {
|
||||
+ match libredox::call::getns() {
|
||||
+ Ok(current_namespace_fd) => {
|
||||
+ if let Err(err) = libredox::call::register_scheme_to_ns(
|
||||
+ current_namespace_fd,
|
||||
+ &scheme,
|
||||
+ new_fd,
|
||||
+ ) {
|
||||
+ eprintln!("init: scheme registration failed for {cmd}: {err}");
|
||||
+ return SpawnStatus::Failed;
|
||||
+ }
|
||||
+ }
|
||||
+ Err(err) => {
|
||||
+ eprintln!("init: getns failed for {cmd}: {err}");
|
||||
+ return SpawnStatus::Failed;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ res
|
||||
+ }
|
||||
+ ServiceType::Oneshot => {
|
||||
+ drop(read_pipe);
|
||||
+ match child.wait() {
|
||||
+ Ok(exit_status) => {
|
||||
+ if !exit_status.success() {
|
||||
+ eprintln!("init: {cmd} failed with {exit_status}");
|
||||
+ SpawnStatus::Failed
|
||||
+ } else {
|
||||
+ SpawnStatus::Success
|
||||
+ }
|
||||
+ }
|
||||
+ Err(err) => {
|
||||
+ eprintln!("init: failed to wait for {cmd}: {err}");
|
||||
+ SpawnStatus::Failed
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
+ ServiceType::OneshotAsync => SpawnStatus::Async,
|
||||
}
|
||||
}
|
||||
diff --git a/init/src/unit.rs b/init/src/unit.rs
|
||||
index 98053cb2d..414b92d17 100644
|
||||
--- a/init/src/unit.rs
|
||||
+++ b/init/src/unit.rs
|
||||
@@ -125,6 +125,25 @@ pub struct UnitInfo {
|
||||
pub condition_architecture: Option<Vec<String>>,
|
||||
// FIXME replace this with hwd reading from the devicetree
|
||||
pub condition_board: Option<Vec<String>>,
|
||||
+ /// Restart policy for the service (only applies to Service units)
|
||||
+ #[serde(default)]
|
||||
+ pub restart: RestartPolicy,
|
||||
+ /// Maximum time in seconds to wait for dependencies before failing (0 = no timeout)
|
||||
+ #[serde(default)]
|
||||
+ pub dependency_timeout_secs: u64,
|
||||
+}
|
||||
+
|
||||
+/// Restart policy for managed services
|
||||
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Default)]
|
||||
+#[serde(rename_all = "kebab-case")]
|
||||
+pub enum RestartPolicy {
|
||||
+ /// Never restart the service (default)
|
||||
+ #[default]
|
||||
+ No,
|
||||
+ /// Restart on failure (non-zero exit or crash)
|
||||
+ OnFailure,
|
||||
+ /// Always restart (on any exit)
|
||||
+ Always,
|
||||
}
|
||||
|
||||
fn true_bool() -> bool {
|
||||
@@ -190,6 +209,8 @@ impl Unit {
|
||||
requires_weak: script.1,
|
||||
condition_architecture: None,
|
||||
condition_board: None,
|
||||
+ restart: RestartPolicy::No,
|
||||
+ dependency_timeout_secs: 0,
|
||||
},
|
||||
kind: UnitKind::LegacyScript { script: script.0 },
|
||||
});
|
||||
@@ -0,0 +1,152 @@
|
||||
diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs
|
||||
index 47588e1..6578761 100644
|
||||
--- a/src/scheme/proc.rs
|
||||
+++ b/src/scheme/proc.rs
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
context::{
|
||||
self,
|
||||
- context::{HardBlockedReason, LockedFdTbl, SignalState},
|
||||
+ context::{HardBlockedReason, LockedFdTbl, SchedPolicy, SignalState},
|
||||
file::InternalFlags,
|
||||
memory::{handle_notify_files, AddrSpace, AddrSpaceWrapper, Grant, PageSpan},
|
||||
Context, ContextLock, Status,
|
||||
@@ -105,6 +105,7 @@ enum ContextHandle {
|
||||
// Attr handles, to set ens/euid/egid/pid.
|
||||
Authority,
|
||||
Attr,
|
||||
+ Groups,
|
||||
|
||||
Status {
|
||||
privileged: bool,
|
||||
@@ -145,6 +146,7 @@ enum ContextHandle {
|
||||
// directory.
|
||||
OpenViaDup,
|
||||
SchedAffinity,
|
||||
+ SchedPolicy,
|
||||
|
||||
MmapMinAddr(Arc<AddrSpaceWrapper>),
|
||||
}
|
||||
@@ -249,6 +251,9 @@ impl ProcScheme {
|
||||
false,
|
||||
),
|
||||
"sched-affinity" => (ContextHandle::SchedAffinity, true),
|
||||
+ // TODO: Switch this kernel-local proc handle over to a stable upstream
|
||||
+ // redox_syscall ProcCall::SetSchedPolicy opcode once that lands.
|
||||
+ "sched-policy" => (ContextHandle::SchedPolicy, false),
|
||||
"status" => (ContextHandle::Status { privileged: false }, false),
|
||||
_ if path.starts_with("auth-") => {
|
||||
let nonprefix = &path["auth-".len()..];
|
||||
@@ -261,6 +266,7 @@ impl ProcScheme {
|
||||
let handle = match actual_name {
|
||||
"attrs" => ContextHandle::Attr,
|
||||
"status" => ContextHandle::Status { privileged: true },
|
||||
+ "groups" => ContextHandle::Groups,
|
||||
_ => return Err(Error::new(ENOENT)),
|
||||
};
|
||||
|
||||
@@ -306,6 +312,11 @@ impl ProcScheme {
|
||||
let id = NonZeroUsize::new(NEXT_ID.fetch_add(1, Ordering::Relaxed))
|
||||
.ok_or(Error::new(EMFILE))?;
|
||||
let context = context::spawn(true, Some(id), ret, token)?;
|
||||
+ {
|
||||
+ let parent_groups =
|
||||
+ context::current().read(token.token()).groups.clone();
|
||||
+ context.write(token.token()).groups = parent_groups;
|
||||
+ }
|
||||
HANDLES.write(token.token()).insert(
|
||||
id.get(),
|
||||
Handle {
|
||||
@@ -1165,6 +1176,20 @@ impl ContextHandle {
|
||||
|
||||
Ok(size_of_val(&mask))
|
||||
}
|
||||
+ Self::SchedPolicy => {
|
||||
+ if buf.len() != 2 {
|
||||
+ return Err(Error::new(EINVAL));
|
||||
+ }
|
||||
+
|
||||
+ let [policy, rt_priority] = unsafe { buf.read_exact::<[u8; 2]>()? };
|
||||
+ let sched_policy = SchedPolicy::try_from_raw(policy).ok_or(Error::new(EINVAL))?;
|
||||
+
|
||||
+ context
|
||||
+ .write(token.token())
|
||||
+ .set_sched_policy(sched_policy, rt_priority);
|
||||
+
|
||||
+ Ok(2)
|
||||
+ }
|
||||
ContextHandle::Status { privileged } => {
|
||||
let mut args = buf.usizes();
|
||||
|
||||
@@ -1268,9 +1293,42 @@ impl ContextHandle {
|
||||
guard.pid = info.pid as usize;
|
||||
guard.euid = info.euid;
|
||||
guard.egid = info.egid;
|
||||
- guard.prio = (info.prio as usize).min(39);
|
||||
+ guard.set_sched_other_prio(info.prio as usize);
|
||||
Ok(size_of::<ProcSchemeAttrs>())
|
||||
}
|
||||
+ Self::Groups => {
|
||||
+ const NGROUPS_MAX: usize = 65536;
|
||||
+ if buf.len() % size_of::<u32>() != 0 {
|
||||
+ return Err(Error::new(EINVAL));
|
||||
+ }
|
||||
+ let count = buf.len() / size_of::<u32>();
|
||||
+ if count > NGROUPS_MAX {
|
||||
+ return Err(Error::new(EINVAL));
|
||||
+ }
|
||||
+ let mut groups = Vec::with_capacity(count);
|
||||
+ for chunk in buf.in_exact_chunks(size_of::<u32>()).take(count) {
|
||||
+ groups.push(chunk.read_u32()?);
|
||||
+ }
|
||||
+ let proc_id = {
|
||||
+ let guard = context.read(token.token());
|
||||
+ guard.owner_proc_id
|
||||
+ };
|
||||
+ {
|
||||
+ let mut guard = context.write(token.token());
|
||||
+ guard.groups = groups.clone();
|
||||
+ }
|
||||
+ if let Some(pid) = proc_id {
|
||||
+ let mut contexts = context::contexts(token.downgrade());
|
||||
+ let (contexts, mut t) = contexts.token_split();
|
||||
+ for context_ref in contexts.iter() {
|
||||
+ let mut ctx = context_ref.write(t.token());
|
||||
+ if ctx.owner_proc_id == Some(pid) {
|
||||
+ ctx.groups = groups.clone();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ Ok(count * size_of::<u32>())
|
||||
+ }
|
||||
ContextHandle::OpenViaDup => {
|
||||
let mut args = buf.usizes();
|
||||
|
||||
@@ -1427,6 +1485,11 @@ impl ContextHandle {
|
||||
|
||||
buf.copy_exactly(crate::cpu_set::mask_as_bytes(&mask))?;
|
||||
Ok(size_of_val(&mask))
|
||||
+ }
|
||||
+ ContextHandle::SchedPolicy => {
|
||||
+ let context = context.read(token.token());
|
||||
+ let data = [context.sched_policy as u8, context.sched_rt_priority];
|
||||
+ buf.copy_common_bytes_from_slice(&data)
|
||||
} // TODO: Replace write() with SYS_SENDFD?
|
||||
ContextHandle::Status { .. } => {
|
||||
let status = {
|
||||
@@ -1475,6 +1538,15 @@ impl ContextHandle {
|
||||
debug_name,
|
||||
})
|
||||
}
|
||||
+ Self::Groups => {
|
||||
+ let c = &context.read(token.token());
|
||||
+ let max = buf.len() / size_of::<u32>();
|
||||
+ let count = c.groups.len().min(max);
|
||||
+ for (chunk, gid) in buf.in_exact_chunks(size_of::<u32>()).zip(&c.groups).take(count) {
|
||||
+ chunk.copy_from_slice(&gid.to_ne_bytes())?;
|
||||
+ }
|
||||
+ Ok(count * size_of::<u32>())
|
||||
+ }
|
||||
ContextHandle::Sighandler => {
|
||||
let data = match context.read(token.token()).sig {
|
||||
Some(ref sig) => SetSighandlerData {
|
||||
@@ -0,0 +1,63 @@
|
||||
diff --git a/src/header/signal/mod.rs b/src/header/signal/mod.rs
|
||||
index f049573..f3d665c 100644
|
||||
--- a/src/header/signal/mod.rs
|
||||
+++ b/src/header/signal/mod.rs
|
||||
@@ -2,7 +2,10 @@
|
||||
//!
|
||||
//! See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/signal.h.html>.
|
||||
|
||||
-use core::{mem, ptr};
|
||||
+use core::{
|
||||
+ mem, ptr,
|
||||
+ sync::atomic::Ordering,
|
||||
+};
|
||||
|
||||
use cbitset::BitSet;
|
||||
|
||||
@@ -32,6 +35,9 @@ pub mod sys;
|
||||
#[path = "redox.rs"]
|
||||
pub mod sys;
|
||||
|
||||
+mod signalfd;
|
||||
+pub use self::signalfd::*;
|
||||
+
|
||||
type SigSet = BitSet<[u64; 1]>;
|
||||
|
||||
pub(crate) const SIG_DFL: usize = 0;
|
||||
@@ -154,10 +160,15 @@ pub extern "C" fn killpg(pgrp: pid_t, sig: c_int) -> c_int {
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_kill.html>.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn pthread_kill(thread: pthread_t, sig: c_int) -> c_int {
|
||||
- let os_tid = {
|
||||
- let pthread = unsafe { &*(thread as *const crate::pthread::Pthread) };
|
||||
- unsafe { pthread.os_tid.get().read() }
|
||||
- };
|
||||
+ let pthread = unsafe { &*(thread as *const crate::pthread::Pthread) };
|
||||
+ let os_tid = unsafe { pthread.os_tid.get().read() };
|
||||
+ let flags = crate::pthread::PthreadFlags::from_bits_retain(
|
||||
+ pthread.flags.load(Ordering::Acquire),
|
||||
+ );
|
||||
+ if flags.contains(crate::pthread::PthreadFlags::FINISHED) {
|
||||
+ return errno::ESRCH;
|
||||
+ }
|
||||
+
|
||||
crate::header::pthread::e(unsafe { Sys::rlct_kill(os_tid, sig as usize) })
|
||||
}
|
||||
|
||||
@@ -168,12 +179,10 @@ pub unsafe extern "C" fn pthread_sigmask(
|
||||
set: *const sigset_t,
|
||||
oldset: *mut sigset_t,
|
||||
) -> c_int {
|
||||
- // On Linux and Redox, pthread_sigmask and sigprocmask are equivalent
|
||||
- if unsafe { sigprocmask(how, set, oldset) } == 0 {
|
||||
- 0
|
||||
- } else {
|
||||
- //TODO: Fix race
|
||||
- platform::ERRNO.get()
|
||||
+ let filtered_set = unsafe { set.as_ref().map(|&block| block & !RLCT_SIGNAL_MASK) };
|
||||
+ match unsafe { Sys::sigprocmask(how, filtered_set.as_ref(), oldset.as_mut()) } {
|
||||
+ Ok(()) => 0,
|
||||
+ Err(errno) => errno.0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
Fix ENOTRECOVERABLE returned for non-robust mutexes and register main
|
||||
thread in OS_TID_TO_PTHREAD.
|
||||
|
||||
The robust mutex liveness check (mutex_owner_id_is_live) was returning
|
||||
ENOTRECOVERABLE for non-robust mutexes when the owner appeared dead.
|
||||
Per POSIX, the behaviour of a non-robust mutex whose owner has died is
|
||||
undefined; returning an error crashes every Rust std::sync::Mutex user.
|
||||
For lock_inner, fall through to spin/futex-wait instead. For try_lock,
|
||||
return EBUSY instead.
|
||||
|
||||
Additionally, pthread::init() never registered the main thread in
|
||||
OS_TID_TO_PTHREAD, so any mutex owned by the main thread would always
|
||||
appear to have a dead owner, making the liveness check unreliable.
|
||||
|
||||
diff --git a/src/pthread/mod.rs b/src/pthread/mod.rs
|
||||
index 8243a48..c455a67 100644
|
||||
--- a/src/pthread/mod.rs
|
||||
+++ b/src/pthread/mod.rs
|
||||
@@ -43,9 +43,13 @@ pub unsafe fn init() {
|
||||
thread.stack_size = STACK_SIZE;
|
||||
}
|
||||
|
||||
- unsafe { Tcb::current() }
|
||||
- .expect_notls("no TCB present for main thread")
|
||||
- .pthread = thread;
|
||||
+ let tcb = unsafe { Tcb::current() }
|
||||
+ .expect_notls("no TCB present for main thread");
|
||||
+ tcb.pthread = thread;
|
||||
+
|
||||
+ OS_TID_TO_PTHREAD
|
||||
+ .lock()
|
||||
+ .insert(Sys::current_os_tid(), ForceSendSync(tcb as *const Tcb as *mut Tcb));
|
||||
}
|
||||
|
||||
//static NEXT_INDEX: AtomicU32 = AtomicU32::new(FIRST_THREAD_IDX + 1);
|
||||
diff --git a/src/sync/pthread_mutex.rs b/src/sync/pthread_mutex.rs
|
||||
index af0c429..1b2b3ca 100644
|
||||
--- a/src/sync/pthread_mutex.rs
|
||||
+++ b/src/sync/pthread_mutex.rs
|
||||
@@ -136,11 +136,7 @@ impl RlctMutex {
|
||||
Err(thread) => {
|
||||
let owner = thread & INDEX_MASK;
|
||||
|
||||
- if !crate::pthread::mutex_owner_id_is_live(owner) {
|
||||
- if !self.robust {
|
||||
- return Err(Errno(ENOTRECOVERABLE));
|
||||
- }
|
||||
-
|
||||
+ if !crate::pthread::mutex_owner_id_is_live(owner) && self.robust {
|
||||
let new_value = (thread & WAITING_BIT) | FUTEX_OWNER_DIED | this_thread;
|
||||
match self.inner.compare_exchange(
|
||||
thread,
|
||||
@@ -152,6 +155,11 @@ impl RlctMutex {
|
||||
Ok(_) => return self.finish_lock_acquire(true),
|
||||
Err(_) => continue,
|
||||
}
|
||||
+ } else if !crate::pthread::mutex_owner_id_is_live(owner) {
|
||||
+ // Non-robust mutex with apparently-dead owner: per POSIX the
|
||||
+ // behaviour is undefined. We conservatively keep spinning /
|
||||
+ // futex-waiting rather than returning ENOTRECOVERABLE, which
|
||||
+ // would crash any Rust std::sync::Mutex user.
|
||||
}
|
||||
|
||||
if spins_left > 0 {
|
||||
@@ -241,9 +250,6 @@ impl RlctMutex {
|
||||
|
||||
if current & FUTEX_OWNER_DIED != 0 || (owner != 0 && !crate::pthread::mutex_owner_id_is_live(owner)) {
|
||||
- if !self.robust {
|
||||
- return Err(Errno(ENOTRECOVERABLE));
|
||||
- }
|
||||
-
|
||||
+ if self.robust {
|
||||
let new_value = (current & WAITING_BIT) | FUTEX_OWNER_DIED | this_thread;
|
||||
match self.inner.compare_exchange(
|
||||
current,
|
||||
@@ -257,6 +269,11 @@ impl RlctMutex {
|
||||
Ok(_) => return self.finish_lock_acquire(true),
|
||||
Err(_) => continue,
|
||||
}
|
||||
+ } else {
|
||||
+ // Non-robust mutex: owner appears dead but POSIX behaviour is
|
||||
+ // undefined; report busy rather than ENOTRECOVERABLE.
|
||||
+ return Err(Errno(EBUSY));
|
||||
+ }
|
||||
}
|
||||
|
||||
return Err(Errno(EBUSY));
|
||||
@@ -0,0 +1,380 @@
|
||||
diff --git a/src/sync/pthread_mutex.rs b/src/sync/pthread_mutex.rs
|
||||
index 29bad63..af0c429 100644
|
||||
--- a/src/sync/pthread_mutex.rs
|
||||
+++ b/src/sync/pthread_mutex.rs
|
||||
@@ -1,3 +1,4 @@
|
||||
+use alloc::boxed::Box;
|
||||
use core::{
|
||||
cell::Cell,
|
||||
sync::atomic::{AtomicU32 as AtomicUint, Ordering},
|
||||
@@ -6,10 +7,9 @@ use core::{
|
||||
use crate::{
|
||||
error::Errno,
|
||||
header::{bits_timespec::timespec, errno::*, pthread::*},
|
||||
+ platform::{Pal, Sys, types::c_int},
|
||||
};
|
||||
|
||||
-use crate::platform::{Pal, Sys, types::c_int};
|
||||
-
|
||||
use super::FutexWaitResult;
|
||||
|
||||
pub struct RlctMutex {
|
||||
@@ -21,15 +21,22 @@ pub struct RlctMutex {
|
||||
robust: bool,
|
||||
}
|
||||
|
||||
+pub struct RobustMutexNode {
|
||||
+ pub next: *mut RobustMutexNode,
|
||||
+ pub prev: *mut RobustMutexNode,
|
||||
+ pub mutex: *const RlctMutex,
|
||||
+}
|
||||
+
|
||||
const STATE_UNLOCKED: u32 = 0;
|
||||
const WAITING_BIT: u32 = 1 << 31;
|
||||
-const INDEX_MASK: u32 = !WAITING_BIT;
|
||||
+const FUTEX_OWNER_DIED: u32 = 1 << 30;
|
||||
+const INDEX_MASK: u32 = !(WAITING_BIT | FUTEX_OWNER_DIED);
|
||||
|
||||
// TODO: Lower limit is probably better.
|
||||
const RECURSIVE_COUNT_MAX_INCLUSIVE: u32 = u32::MAX;
|
||||
// TODO: How many spins should we do before it becomes more time-economical to enter kernel mode
|
||||
// via futexes?
|
||||
-const SPIN_COUNT: usize = 0;
|
||||
+const SPIN_COUNT: usize = 100;
|
||||
|
||||
impl RlctMutex {
|
||||
pub(crate) fn new(attr: &RlctMutexAttr) -> Result<Self, Errno> {
|
||||
@@ -69,13 +76,25 @@ impl RlctMutex {
|
||||
Ok(0)
|
||||
}
|
||||
pub fn make_consistent(&self) -> Result<(), Errno> {
|
||||
- todo_skip!(0, "pthread robust mutexes: not implemented");
|
||||
- Ok(())
|
||||
+ debug_assert!(self.robust, "make_consistent called on non-robust mutex");
|
||||
+
|
||||
+ if !self.robust {
|
||||
+ return Err(Errno(EINVAL));
|
||||
+ }
|
||||
+
|
||||
+ let current = self.inner.load(Ordering::Relaxed);
|
||||
+ let owner = current & INDEX_MASK;
|
||||
+
|
||||
+ if owner == os_tid_invalid_after_fork() && current & FUTEX_OWNER_DIED != 0 {
|
||||
+ self.inner.store(0, Ordering::Release);
|
||||
+ Ok(())
|
||||
+ } else {
|
||||
+ Err(Errno(EINVAL))
|
||||
+ }
|
||||
}
|
||||
fn lock_inner(&self, deadline: Option<×pec>) -> Result<(), Errno> {
|
||||
let this_thread = os_tid_invalid_after_fork();
|
||||
-
|
||||
- //let mut spins_left = SPIN_COUNT;
|
||||
+ let mut spins_left = SPIN_COUNT;
|
||||
|
||||
loop {
|
||||
let result = self.inner.compare_exchange_weak(
|
||||
@@ -86,45 +105,59 @@ impl RlctMutex {
|
||||
);
|
||||
|
||||
match result {
|
||||
- // CAS succeeded
|
||||
- Ok(_) => {
|
||||
- if self.ty == Ty::Recursive {
|
||||
- self.increment_recursive_count()?;
|
||||
- }
|
||||
- return Ok(());
|
||||
- }
|
||||
- // CAS failed, but the mutex was recursive and we already own the lock.
|
||||
+ Ok(_) => return self.finish_lock_acquire(false),
|
||||
Err(thread) if thread & INDEX_MASK == this_thread && self.ty == Ty::Recursive => {
|
||||
self.increment_recursive_count()?;
|
||||
return Ok(());
|
||||
}
|
||||
- // CAS failed, but the mutex was error-checking and we already own the lock.
|
||||
Err(thread) if thread & INDEX_MASK == this_thread && self.ty == Ty::Errck => {
|
||||
- return Err(Errno(EAGAIN));
|
||||
+ return Err(Errno(EDEADLK));
|
||||
}
|
||||
- // CAS spuriously failed, simply retry the CAS. TODO: Use core::hint::spin_loop()?
|
||||
- Err(thread) if thread & INDEX_MASK == 0 => {
|
||||
- continue;
|
||||
+ Err(thread) if thread & FUTEX_OWNER_DIED != 0 && thread & INDEX_MASK == 0 => {
|
||||
+ return Err(Errno(ENOTRECOVERABLE));
|
||||
}
|
||||
- // CAS failed because some other thread owned the lock. We must now wait.
|
||||
+ Err(thread) if thread & FUTEX_OWNER_DIED != 0 => {
|
||||
+ if !self.robust {
|
||||
+ return Err(Errno(ENOTRECOVERABLE));
|
||||
+ }
|
||||
+
|
||||
+ let new_value = (thread & WAITING_BIT) | FUTEX_OWNER_DIED | this_thread;
|
||||
+ match self.inner.compare_exchange(
|
||||
+ thread,
|
||||
+ new_value,
|
||||
+ Ordering::Acquire,
|
||||
+ Ordering::Relaxed,
|
||||
+ ) {
|
||||
+ Ok(_) => return self.finish_lock_acquire(true),
|
||||
+ Err(_) => continue,
|
||||
+ }
|
||||
+ }
|
||||
+ Err(thread) if thread & INDEX_MASK == 0 => continue,
|
||||
Err(thread) => {
|
||||
- /*if spins_left > 0 {
|
||||
- // TODO: Faster to spin trying to load the flag, compared to CAS?
|
||||
+ let owner = thread & INDEX_MASK;
|
||||
+
|
||||
+ if !crate::pthread::mutex_owner_id_is_live(owner) {
|
||||
+ if !self.robust {
|
||||
+ return Err(Errno(ENOTRECOVERABLE));
|
||||
+ }
|
||||
+
|
||||
+ let new_value = (thread & WAITING_BIT) | FUTEX_OWNER_DIED | this_thread;
|
||||
+ match self.inner.compare_exchange(
|
||||
+ thread,
|
||||
+ new_value,
|
||||
+ Ordering::Acquire,
|
||||
+ Ordering::Relaxed,
|
||||
+ ) {
|
||||
+ Ok(_) => return self.finish_lock_acquire(true),
|
||||
+ Err(_) => continue,
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if spins_left > 0 {
|
||||
spins_left -= 1;
|
||||
core::hint::spin_loop();
|
||||
continue;
|
||||
}
|
||||
-
|
||||
- spins_left = SPIN_COUNT;
|
||||
-
|
||||
- let inner = self.inner.fetch_or(WAITING_BIT, Ordering::Relaxed);
|
||||
-
|
||||
- if inner == STATE_UNLOCKED {
|
||||
- continue;
|
||||
- }*/
|
||||
-
|
||||
- // If the mutex is not robust, simply futex_wait until unblocked.
|
||||
- //crate::sync::futex_wait(&self.inner, inner | WAITING_BIT, None);
|
||||
if crate::sync::futex_wait(&self.inner, thread, deadline)
|
||||
== FutexWaitResult::TimedOut
|
||||
{
|
||||
@@ -140,6 +173,20 @@ impl RlctMutex {
|
||||
pub fn lock_with_timeout(&self, deadline: ×pec) -> Result<(), Errno> {
|
||||
self.lock_inner(Some(deadline))
|
||||
}
|
||||
+ fn finish_lock_acquire(&self, owner_dead: bool) -> Result<(), Errno> {
|
||||
+ if self.ty == Ty::Recursive {
|
||||
+ self.increment_recursive_count()?;
|
||||
+ }
|
||||
+ if self.robust {
|
||||
+ add_to_robust_list(self);
|
||||
+ }
|
||||
+
|
||||
+ if owner_dead {
|
||||
+ Err(Errno(EOWNERDEAD))
|
||||
+ } else {
|
||||
+ Ok(())
|
||||
+ }
|
||||
+ }
|
||||
fn increment_recursive_count(&self) -> Result<(), Errno> {
|
||||
// We don't have to worry about asynchronous signals here, since pthread_mutex_trylock
|
||||
// is not async-signal-safe.
|
||||
@@ -161,41 +208,65 @@ impl RlctMutex {
|
||||
pub fn try_lock(&self) -> Result<(), Errno> {
|
||||
let this_thread = os_tid_invalid_after_fork();
|
||||
|
||||
- // TODO: If recursive, omitting CAS may be faster if it is already owned by this thread.
|
||||
- let result = self.inner.compare_exchange(
|
||||
- STATE_UNLOCKED,
|
||||
- this_thread,
|
||||
- Ordering::Acquire,
|
||||
- Ordering::Relaxed,
|
||||
- );
|
||||
+ loop {
|
||||
+ let current = self.inner.load(Ordering::Relaxed);
|
||||
+
|
||||
+ if current == STATE_UNLOCKED {
|
||||
+ match self.inner.compare_exchange(
|
||||
+ STATE_UNLOCKED,
|
||||
+ this_thread,
|
||||
+ Ordering::Acquire,
|
||||
+ Ordering::Relaxed,
|
||||
+ ) {
|
||||
+ Ok(_) => return self.finish_lock_acquire(false),
|
||||
+ Err(_) => continue,
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- if self.ty == Ty::Recursive {
|
||||
- match result {
|
||||
- Err(index) if index & INDEX_MASK != this_thread => return Err(Errno(EBUSY)),
|
||||
- _ => (),
|
||||
+ let owner = current & INDEX_MASK;
|
||||
+
|
||||
+ if owner == this_thread && self.ty == Ty::Recursive {
|
||||
+ self.increment_recursive_count()?;
|
||||
+ return Ok(());
|
||||
}
|
||||
|
||||
- self.increment_recursive_count()?;
|
||||
+ if owner == this_thread && self.ty == Ty::Errck {
|
||||
+ return Err(Errno(EDEADLK));
|
||||
+ }
|
||||
|
||||
- return Ok(());
|
||||
- }
|
||||
+ if current & FUTEX_OWNER_DIED != 0 && owner == 0 {
|
||||
+ return Err(Errno(ENOTRECOVERABLE));
|
||||
+ }
|
||||
|
||||
- match result {
|
||||
- Ok(_) => Ok(()),
|
||||
- Err(index) if index & INDEX_MASK == this_thread && self.ty == Ty::Errck => {
|
||||
- Err(Errno(EDEADLK))
|
||||
+ if current & FUTEX_OWNER_DIED != 0 || (owner != 0 && !crate::pthread::mutex_owner_id_is_live(owner)) {
|
||||
+ if !self.robust {
|
||||
+ return Err(Errno(ENOTRECOVERABLE));
|
||||
+ }
|
||||
+
|
||||
+ let new_value = (current & WAITING_BIT) | FUTEX_OWNER_DIED | this_thread;
|
||||
+ match self.inner.compare_exchange(
|
||||
+ current,
|
||||
+ new_value,
|
||||
+ Ordering::Acquire,
|
||||
+ Ordering::Relaxed,
|
||||
+ ) {
|
||||
+ Ok(_) => return self.finish_lock_acquire(true),
|
||||
+ Err(_) => continue,
|
||||
+ }
|
||||
}
|
||||
- Err(_) => Err(Errno(EBUSY)),
|
||||
+
|
||||
+ return Err(Errno(EBUSY));
|
||||
}
|
||||
}
|
||||
// Safe because we are not protecting any data.
|
||||
pub fn unlock(&self) -> Result<(), Errno> {
|
||||
+ let current = self.inner.load(Ordering::Relaxed);
|
||||
+
|
||||
if self.robust || matches!(self.ty, Ty::Recursive | Ty::Errck) {
|
||||
- if self.inner.load(Ordering::Relaxed) & INDEX_MASK != os_tid_invalid_after_fork() {
|
||||
+ if current & INDEX_MASK != os_tid_invalid_after_fork() {
|
||||
return Err(Errno(EPERM));
|
||||
}
|
||||
|
||||
- // TODO: Is this fence correct?
|
||||
core::sync::atomic::fence(Ordering::Acquire);
|
||||
}
|
||||
|
||||
@@ -208,18 +279,47 @@ impl RlctMutex {
|
||||
}
|
||||
}
|
||||
|
||||
- self.inner.store(STATE_UNLOCKED, Ordering::Release);
|
||||
- crate::sync::futex_wake(&self.inner, i32::MAX);
|
||||
- /*let was_waiting = self.inner.swap(STATE_UNLOCKED, Ordering::Release) & WAITING_BIT != 0;
|
||||
+ if self.robust {
|
||||
+ remove_from_robust_list(self);
|
||||
+ }
|
||||
|
||||
- if was_waiting {
|
||||
- let _ = crate::sync::futex_wake(&self.inner, 1);
|
||||
- }*/
|
||||
+ let new_state = if self.robust && current & FUTEX_OWNER_DIED != 0 {
|
||||
+ FUTEX_OWNER_DIED
|
||||
+ } else {
|
||||
+ STATE_UNLOCKED
|
||||
+ };
|
||||
+
|
||||
+ self.inner.store(new_state, Ordering::Release);
|
||||
+ crate::sync::futex_wake(&self.inner, i32::MAX);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
+pub(crate) unsafe fn mark_robust_mutexes_dead(thread: &crate::pthread::Pthread) {
|
||||
+ let head = thread.robust_list_head.get();
|
||||
+ let this_thread = os_tid_invalid_after_fork();
|
||||
+ let mut node = unsafe { *head };
|
||||
+
|
||||
+ unsafe { *head = core::ptr::null_mut() };
|
||||
+
|
||||
+ while !node.is_null() {
|
||||
+ let next = unsafe { (*node).next };
|
||||
+ let mutex = unsafe { &*(*node).mutex };
|
||||
+ let current = mutex.inner.load(Ordering::Relaxed);
|
||||
+
|
||||
+ if current & INDEX_MASK == this_thread {
|
||||
+ mutex
|
||||
+ .inner
|
||||
+ .store((current & WAITING_BIT) | FUTEX_OWNER_DIED | this_thread, Ordering::Release);
|
||||
+ crate::sync::futex_wake(&mutex.inner, i32::MAX);
|
||||
+ }
|
||||
+
|
||||
+ unsafe { drop(Box::from_raw(node)) };
|
||||
+ node = next;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
#[repr(u8)]
|
||||
#[derive(PartialEq)]
|
||||
enum Ty {
|
||||
@@ -237,6 +337,54 @@ enum Ty {
|
||||
#[thread_local]
|
||||
static CACHED_OS_TID_INVALID_AFTER_FORK: Cell<u32> = Cell::new(0);
|
||||
|
||||
+fn add_to_robust_list(mutex: &RlctMutex) {
|
||||
+ let thread = crate::pthread::current_thread().expect("current thread not present");
|
||||
+ let node_ptr = Box::into_raw(Box::new(RobustMutexNode {
|
||||
+ next: core::ptr::null_mut(),
|
||||
+ prev: core::ptr::null_mut(),
|
||||
+ mutex: core::ptr::from_ref(mutex),
|
||||
+ }));
|
||||
+
|
||||
+ unsafe {
|
||||
+ let head = thread.robust_list_head.get();
|
||||
+ if !(*head).is_null() {
|
||||
+ (**head).prev = node_ptr;
|
||||
+ }
|
||||
+ (*node_ptr).next = *head;
|
||||
+ *head = node_ptr;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+fn remove_from_robust_list(mutex: &RlctMutex) {
|
||||
+ let thread = match crate::pthread::current_thread() {
|
||||
+ Some(thread) => thread,
|
||||
+ None => return,
|
||||
+ };
|
||||
+
|
||||
+ unsafe {
|
||||
+ let mut node = *thread.robust_list_head.get();
|
||||
+
|
||||
+ while !node.is_null() {
|
||||
+ if core::ptr::eq((*node).mutex, core::ptr::from_ref(mutex)) {
|
||||
+ if !(*node).prev.is_null() {
|
||||
+ (*(*node).prev).next = (*node).next;
|
||||
+ } else {
|
||||
+ *thread.robust_list_head.get() = (*node).next;
|
||||
+ }
|
||||
+
|
||||
+ if !(*node).next.is_null() {
|
||||
+ (*(*node).next).prev = (*node).prev;
|
||||
+ }
|
||||
+
|
||||
+ drop(Box::from_raw(node));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ node = (*node).next;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
// Assumes TIDs are unique between processes, which I only know is true for Redox.
|
||||
fn os_tid_invalid_after_fork() -> u32 {
|
||||
// TODO: Coordinate better if using shared == PTHREAD_PROCESS_SHARED, with up to 2^32 separate
|
||||
@@ -0,0 +1,130 @@
|
||||
diff --git a/src/header/sched/mod.rs b/src/header/sched/mod.rs
|
||||
index bcdd346..6066550 100644
|
||||
--- a/src/header/sched/mod.rs
|
||||
+++ b/src/header/sched/mod.rs
|
||||
@@ -27,43 +27,110 @@ pub const SCHED_RR: c_int = 1;
|
||||
pub const SCHED_OTHER: c_int = 2;
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sched_get_priority_max.html>.
|
||||
-// #[unsafe(no_mangle)]
|
||||
+#[unsafe(no_mangle)]
|
||||
pub extern "C" fn sched_get_priority_max(policy: c_int) -> c_int {
|
||||
- todo!()
|
||||
+ match policy {
|
||||
+ SCHED_FIFO | SCHED_RR => 99,
|
||||
+ SCHED_OTHER => 0,
|
||||
+ _ => {
|
||||
+ crate::platform::ERRNO.set(crate::header::errno::EINVAL);
|
||||
+ -1
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
-/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sched_get_priority_max.html>.
|
||||
-// #[unsafe(no_mangle)]
|
||||
+/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sched_get_priority_min.html>.
|
||||
+#[unsafe(no_mangle)]
|
||||
pub extern "C" fn sched_get_priority_min(policy: c_int) -> c_int {
|
||||
- todo!()
|
||||
+ match policy {
|
||||
+ SCHED_FIFO | SCHED_RR => 1,
|
||||
+ SCHED_OTHER => 0,
|
||||
+ _ => {
|
||||
+ crate::platform::ERRNO.set(crate::header::errno::EINVAL);
|
||||
+ -1
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sched_getparam.html>.
|
||||
-// #[unsafe(no_mangle)]
|
||||
+#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn sched_getparam(pid: pid_t, param: *mut sched_param) -> c_int {
|
||||
- todo!()
|
||||
+ if pid != 0 {
|
||||
+ crate::platform::ERRNO.set(crate::header::errno::ESRCH);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ crate::platform::ERRNO.set(crate::header::errno::ENOSYS);
|
||||
+ -1
|
||||
+}
|
||||
+
|
||||
+/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sched_getscheduler.html>.
|
||||
+#[unsafe(no_mangle)]
|
||||
+pub extern "C" fn sched_getscheduler(pid: pid_t) -> c_int {
|
||||
+ if pid != 0 {
|
||||
+ crate::platform::ERRNO.set(crate::header::errno::ESRCH);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ crate::platform::ERRNO.set(crate::header::errno::ENOSYS);
|
||||
+ -1
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sched_rr_get_interval.html>.
|
||||
-// #[unsafe(no_mangle)]
|
||||
-pub extern "C" fn sched_rr_get_interval(pid: pid_t, time: *const timespec) -> c_int {
|
||||
- todo!()
|
||||
+#[unsafe(no_mangle)]
|
||||
+pub extern "C" fn sched_rr_get_interval(pid: pid_t, tp: *mut timespec) -> c_int {
|
||||
+ if pid != 0 {
|
||||
+ crate::platform::ERRNO.set(crate::header::errno::ESRCH);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ if tp.is_null() {
|
||||
+ crate::platform::ERRNO.set(crate::header::errno::EINVAL);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ unsafe {
|
||||
+ (*tp).tv_sec = 0;
|
||||
+ (*tp).tv_nsec = 100_000_000; // 100ms default SCHED_RR quantum
|
||||
+ }
|
||||
+ 0
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sched_setparam.html>.
|
||||
-// #[unsafe(no_mangle)]
|
||||
-pub unsafe extern "C" fn sched_setparam(pid: pid_t, param: *const sched_param) -> c_int {
|
||||
- todo!()
|
||||
+#[unsafe(no_mangle)]
|
||||
+pub unsafe extern "C" fn sched_setparam(pid: pid_t, _param: *const sched_param) -> c_int {
|
||||
+ if pid != 0 {
|
||||
+ crate::platform::ERRNO.set(crate::header::errno::ESRCH);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ crate::platform::ERRNO.set(crate::header::errno::ENOSYS);
|
||||
+ -1
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sched_setscheduler.html>.
|
||||
-// #[unsafe(no_mangle)]
|
||||
+#[unsafe(no_mangle)]
|
||||
pub extern "C" fn sched_setscheduler(
|
||||
pid: pid_t,
|
||||
policy: c_int,
|
||||
param: *const sched_param,
|
||||
) -> c_int {
|
||||
- todo!()
|
||||
+ if pid != 0 {
|
||||
+ crate::platform::ERRNO.set(crate::header::errno::ESRCH);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ match policy {
|
||||
+ SCHED_OTHER => {
|
||||
+ if !param.is_null() && unsafe { (*param).sched_priority } != 0 {
|
||||
+ crate::platform::ERRNO.set(crate::header::errno::EINVAL);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ SCHED_OTHER
|
||||
+ }
|
||||
+ SCHED_FIFO | SCHED_RR => {
|
||||
+ crate::platform::ERRNO.set(crate::header::errno::ENOSYS);
|
||||
+ -1
|
||||
+ }
|
||||
+ _ => {
|
||||
+ crate::platform::ERRNO.set(crate::header::errno::EINVAL);
|
||||
+ -1
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sched_yield.html>.
|
||||
@@ -0,0 +1,176 @@
|
||||
diff --git a/src/context/context.rs b/src/context/context.rs
|
||||
index c97c516..8a8b078 100644
|
||||
--- a/src/context/context.rs
|
||||
+++ b/src/context/context.rs
|
||||
@@ -18,7 +18,8 @@ use crate::{
|
||||
cpu_stats,
|
||||
ipi::{ipi, IpiKind, IpiTarget},
|
||||
memory::{
|
||||
- allocate_p2frame, deallocate_p2frame, Enomem, Frame, RaiiFrame, RmmA, RmmArch, PAGE_SIZE,
|
||||
+ allocate_p2frame, deallocate_p2frame, Enomem, Frame, PhysicalAddress, RaiiFrame, RmmA,
|
||||
+ RmmArch, PAGE_SIZE,
|
||||
},
|
||||
percpu::PercpuBlock,
|
||||
scheme::{CallerCtx, FileHandle, SchemeId},
|
||||
@@ -62,6 +63,38 @@ impl Status {
|
||||
}
|
||||
}
|
||||
|
||||
+pub const SCHED_PRIORITY_LEVELS: usize = 40;
|
||||
+pub const DEFAULT_SCHED_OTHER_PRIORITY: usize = 20;
|
||||
+pub const DEFAULT_SCHED_RR_QUANTUM: u128 = 100_000_000;
|
||||
+
|
||||
+#[repr(u8)]
|
||||
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
+pub enum SchedPolicy {
|
||||
+ Fifo = 0,
|
||||
+ RoundRobin = 1,
|
||||
+ Other = 2,
|
||||
+}
|
||||
+
|
||||
+impl SchedPolicy {
|
||||
+ pub fn try_from_raw(raw: u8) -> Option<Self> {
|
||||
+ match raw {
|
||||
+ 0 => Some(Self::Fifo),
|
||||
+ 1 => Some(Self::RoundRobin),
|
||||
+ 2 => Some(Self::Other),
|
||||
+ _ => None,
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+pub fn rt_priority_to_kernel_prio(rt_priority: u8) -> usize {
|
||||
+ (SCHED_PRIORITY_LEVELS - 1)
|
||||
+ .saturating_sub((usize::from(rt_priority.min(99)) * (SCHED_PRIORITY_LEVELS - 1)) / 99)
|
||||
+}
|
||||
+
|
||||
+fn clamp_sched_other_prio(prio: usize) -> usize {
|
||||
+ prio.min(SCHED_PRIORITY_LEVELS - 1)
|
||||
+}
|
||||
+
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum HardBlockedReason {
|
||||
/// "SIGSTOP", only procmgr is allowed to switch contexts this state
|
||||
@@ -140,6 +173,17 @@ pub struct Context {
|
||||
pub fmap_ret: Option<Frame>,
|
||||
/// Priority
|
||||
pub prio: usize,
|
||||
+ pub sched_policy: SchedPolicy,
|
||||
+ pub sched_rt_priority: u8,
|
||||
+ pub sched_rr_ticks_consumed: u32,
|
||||
+ pub sched_static_prio: usize,
|
||||
+ pub sched_rr_quantum: u128,
|
||||
+ #[allow(dead_code)]
|
||||
+ pub futex_pi_boost: bool,
|
||||
+ #[allow(dead_code)]
|
||||
+ pub futex_pi_original_prio: usize,
|
||||
+ #[allow(dead_code)]
|
||||
+ pub futex_pi_waiters: Vec<PhysicalAddress>,
|
||||
|
||||
// TODO: id can reappear after wraparound?
|
||||
pub owner_proc_id: Option<NonZeroUsize>,
|
||||
@@ -148,6 +192,8 @@ pub struct Context {
|
||||
pub euid: u32,
|
||||
pub egid: u32,
|
||||
pub pid: usize,
|
||||
+ /// Supplementary group IDs for access control decisions.
|
||||
+ pub groups: Vec<u32>,
|
||||
|
||||
// See [`PreemptGuard`]
|
||||
//
|
||||
@@ -197,13 +243,22 @@ impl Context {
|
||||
files: Arc::new(RwLock::new(FdTbl::new())),
|
||||
userspace: false,
|
||||
fmap_ret: None,
|
||||
- prio: 20,
|
||||
+ prio: DEFAULT_SCHED_OTHER_PRIORITY,
|
||||
+ sched_policy: SchedPolicy::Other,
|
||||
+ sched_rt_priority: 0,
|
||||
+ sched_rr_ticks_consumed: 0,
|
||||
+ sched_static_prio: DEFAULT_SCHED_OTHER_PRIORITY,
|
||||
+ sched_rr_quantum: DEFAULT_SCHED_RR_QUANTUM,
|
||||
+ futex_pi_boost: false,
|
||||
+ futex_pi_original_prio: DEFAULT_SCHED_OTHER_PRIORITY,
|
||||
+ futex_pi_waiters: Vec::new(),
|
||||
being_sigkilled: false,
|
||||
owner_proc_id,
|
||||
|
||||
euid: 0,
|
||||
egid: 0,
|
||||
pid: 0,
|
||||
+ groups: Vec::new(),
|
||||
|
||||
#[cfg(feature = "syscall_debug")]
|
||||
syscall_debug_info: crate::syscall::debug::SyscallDebugInfo::default(),
|
||||
@@ -218,11 +273,47 @@ impl Context {
|
||||
self.preempt_locks == 0
|
||||
}
|
||||
|
||||
+ fn base_sched_prio(&self) -> usize {
|
||||
+ match self.sched_policy {
|
||||
+ SchedPolicy::Other => clamp_sched_other_prio(self.sched_static_prio),
|
||||
+ SchedPolicy::Fifo | SchedPolicy::RoundRobin => {
|
||||
+ rt_priority_to_kernel_prio(self.sched_rt_priority)
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ fn apply_sched_prio(&mut self) {
|
||||
+ let base_prio = self.base_sched_prio();
|
||||
+ if self.futex_pi_boost {
|
||||
+ self.futex_pi_original_prio = base_prio;
|
||||
+ self.prio = self.prio.min(base_prio);
|
||||
+ } else {
|
||||
+ self.futex_pi_original_prio = base_prio;
|
||||
+ self.prio = base_prio;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ pub fn set_sched_other_prio(&mut self, prio: usize) {
|
||||
+ self.sched_static_prio = clamp_sched_other_prio(prio);
|
||||
+ self.apply_sched_prio();
|
||||
+ }
|
||||
+
|
||||
+ pub fn set_sched_policy(&mut self, sched_policy: SchedPolicy, rt_priority: u8) {
|
||||
+ self.sched_policy = sched_policy;
|
||||
+ self.sched_rt_priority = match sched_policy {
|
||||
+ SchedPolicy::Other => 0,
|
||||
+ SchedPolicy::Fifo | SchedPolicy::RoundRobin => rt_priority.min(99),
|
||||
+ };
|
||||
+ self.sched_rr_ticks_consumed = 0;
|
||||
+ self.apply_sched_prio();
|
||||
+ }
|
||||
+
|
||||
/// Block the context, and return true if it was runnable before being blocked
|
||||
pub fn block(&mut self, reason: &'static str) -> bool {
|
||||
if self.status.is_runnable() {
|
||||
self.status = Status::Blocked;
|
||||
self.status_reason = reason;
|
||||
+ self.sched_rr_ticks_consumed = 0;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@@ -232,6 +323,7 @@ impl Context {
|
||||
pub fn hard_block(&mut self, reason: HardBlockedReason) -> bool {
|
||||
if self.status.is_runnable() {
|
||||
self.status = Status::HardBlocked { reason };
|
||||
+ self.sched_rr_ticks_consumed = 0;
|
||||
|
||||
true
|
||||
} else {
|
||||
@@ -261,6 +353,7 @@ impl Context {
|
||||
if self.status.is_soft_blocked() {
|
||||
self.status = Status::Runnable;
|
||||
self.status_reason = "";
|
||||
+ self.sched_rr_ticks_consumed = 0;
|
||||
|
||||
true
|
||||
} else {
|
||||
@@ -479,6 +572,7 @@ impl Context {
|
||||
uid: self.euid,
|
||||
gid: self.egid,
|
||||
pid: self.pid,
|
||||
+ groups: self.groups.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
diff --git a/src/context/switch.rs b/src/context/switch.rs
|
||||
index 86684c8..aeb29c9 100644
|
||||
--- a/src/context/switch.rs
|
||||
+++ b/src/context/switch.rs
|
||||
@@ -5,7 +5,7 @@
|
||||
use crate::{
|
||||
context::{
|
||||
self, arch, idle_contexts, idle_contexts_try, run_contexts, ArcContextLockWriteGuard,
|
||||
- Context, ContextLock, WeakContextRef,
|
||||
+ Context, ContextLock, SchedPolicy, WeakContextRef,
|
||||
},
|
||||
cpu_set::LogicalCpuId,
|
||||
cpu_stats::{self, CpuState},
|
||||
@@ -33,35 +33,17 @@ const SCHED_PRIO_TO_WEIGHT: [usize; 40] = [
|
||||
70, 56, 45, 36, 29, 23, 18, 15,
|
||||
];
|
||||
|
||||
-/// Determines if a given context is eligible to be scheduled on a given CPU (in
|
||||
-/// principle, the current CPU).
|
||||
-///
|
||||
-/// # Safety
|
||||
-/// This function is unsafe because it modifies the `context`'s state directly without synchronization.
|
||||
-///
|
||||
-/// # Parameters
|
||||
-/// - `context`: The context (process/thread) to be checked.
|
||||
-/// - `cpu_id`: The logical ID of the CPU on which the context is being scheduled.
|
||||
-///
|
||||
-/// # Returns
|
||||
-/// - `UpdateResult::CanSwitch`: If the context can be switched to.
|
||||
-/// - `UpdateResult::Skip`: If the context should be skipped (e.g., it's running on another CPU).
|
||||
unsafe fn update_runnable(
|
||||
context: &mut Context,
|
||||
cpu_id: LogicalCpuId,
|
||||
switch_time: u128,
|
||||
) -> UpdateResult {
|
||||
- // Ignore contexts that are already running.
|
||||
if context.running {
|
||||
return UpdateResult::Skip;
|
||||
}
|
||||
-
|
||||
- // Ignore contexts assigned to other CPUs.
|
||||
if !context.sched_affinity.contains(cpu_id) {
|
||||
return UpdateResult::Skip;
|
||||
}
|
||||
-
|
||||
- // If context is soft-blocked and has a wake-up time, check if it should wake up.
|
||||
if context.status.is_soft_blocked()
|
||||
&& let Some(wake) = context.wake
|
||||
&& switch_time >= wake
|
||||
@@ -69,8 +51,6 @@ unsafe fn update_runnable(
|
||||
context.wake = None;
|
||||
context.unblock_no_ipi();
|
||||
}
|
||||
-
|
||||
- // If the context is runnable, indicate it can be switched to.
|
||||
if context.status.is_runnable() {
|
||||
UpdateResult::CanSwitch
|
||||
} else {
|
||||
@@ -95,7 +75,7 @@ pub fn tick(token: &mut CleanLockToken) {
|
||||
let new_ticks = ticks_cell.get() + 1;
|
||||
ticks_cell.set(new_ticks);
|
||||
|
||||
- // Trigger a context switch after every 3 ticks (approx. 6.75 ms).
|
||||
+ // Trigger a context switch after every 3 ticks.
|
||||
if new_ticks >= 3 {
|
||||
switch(token);
|
||||
crate::context::signal::signal_handler(token);
|
||||
@@ -167,10 +147,7 @@ pub fn switch(token: &mut CleanLockToken) -> SwitchResult {
|
||||
let mut prev_context_guard = unsafe { prev_context_lock.write_arc() };
|
||||
|
||||
if !prev_context_guard.is_preemptable() {
|
||||
- // Unset global lock
|
||||
arch::CONTEXT_SWITCH_LOCK.store(false, Ordering::SeqCst);
|
||||
-
|
||||
- // Pretend to have finished switching, so CPU is not idled
|
||||
return SwitchResult::Switched;
|
||||
}
|
||||
|
||||
@@ -377,6 +354,71 @@ fn select_next_context(
|
||||
let total_contexts: usize = contexts_list.iter().map(|q| q.len()).sum();
|
||||
let mut skipped_contexts = 0;
|
||||
|
||||
+ // PASS 0: SCHED_FIFO and SCHED_RR — scan for RT contexts to schedule.
|
||||
+ // When a runnable RT context is found, it takes priority over all SCHED_OTHER.
|
||||
+ for prio in 0..40 {
|
||||
+ let rt_contexts = contexts_list
|
||||
+ .get_mut(prio)
|
||||
+ .expect("prio should be between [0, 39]");
|
||||
+ let len = rt_contexts.len();
|
||||
+ for _ in 0..len {
|
||||
+ let (rt_ref, rt_lock) = match rt_contexts.pop_front() {
|
||||
+ Some(lock) => match lock.upgrade() {
|
||||
+ Some(l) => (lock, l),
|
||||
+ None => {
|
||||
+ skipped_contexts += 1;
|
||||
+ continue;
|
||||
+ }
|
||||
+ },
|
||||
+ None => break,
|
||||
+ };
|
||||
+ if Arc::ptr_eq(&rt_lock, &idle_context) {
|
||||
+ rt_contexts.push_back(rt_ref);
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Current RT thread: if runnable with no higher-prio RT found yet,
|
||||
+ // keep it running (no demotion to SCHED_OTHER)
|
||||
+ if Arc::ptr_eq(&rt_lock, &prev_context_lock) {
|
||||
+ let mut rt_guard = unsafe { rt_lock.write_arc() };
|
||||
+ if rt_guard.status.is_runnable()
|
||||
+ && (rt_guard.sched_policy == SchedPolicy::Fifo
|
||||
+ || rt_guard.sched_policy == SchedPolicy::RoundRobin)
|
||||
+ {
|
||||
+ percpu.balance.set(balance);
|
||||
+ percpu.last_queue.set(i);
|
||||
+ return Ok(Some(rt_guard));
|
||||
+ }
|
||||
+ rt_contexts.push_back(rt_ref);
|
||||
+ continue;
|
||||
+ }
|
||||
+ let mut rt_guard = unsafe { rt_lock.write_arc() };
|
||||
+ if !rt_guard.status.is_runnable() || rt_guard.running
|
||||
+ || !rt_guard.sched_affinity.contains(cpu_id)
|
||||
+ {
|
||||
+ rt_contexts.push_back(rt_ref);
|
||||
+ continue;
|
||||
+ }
|
||||
+ if rt_guard.sched_policy == SchedPolicy::Fifo
|
||||
+ || rt_guard.sched_policy == SchedPolicy::RoundRobin
|
||||
+ {
|
||||
+ percpu.balance.set(balance);
|
||||
+ percpu.last_queue.set(i);
|
||||
+ if !Arc::ptr_eq(&prev_context_lock, &idle_context) {
|
||||
+ let prev_ctx = WeakContextRef(Arc::downgrade(&prev_context_lock));
|
||||
+ if prev_context_guard.status.is_runnable() {
|
||||
+ contexts_list[prev_context_guard.prio].push_back(prev_ctx);
|
||||
+ } else {
|
||||
+ idle_contexts(token.token()).push_back(prev_ctx);
|
||||
+ }
|
||||
+ }
|
||||
+ return Ok(Some(rt_guard));
|
||||
+ }
|
||||
+ rt_contexts.push_back(rt_ref);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // PASS 1: SCHED_OTHER — existing DWRR deficit tracking
|
||||
+
|
||||
'priority: loop {
|
||||
i = (i + 1) % 40;
|
||||
total_iters += 1;
|
||||
@@ -0,0 +1,20 @@
|
||||
diff --git a/src/scheme/mod.rs b/src/scheme/mod.rs
|
||||
index d30272c..9da2b28 100644
|
||||
--- a/src/scheme/mod.rs
|
||||
+++ b/src/scheme/mod.rs
|
||||
@@ -777,6 +777,7 @@ pub struct CallerCtx {
|
||||
pub pid: usize,
|
||||
pub uid: u32,
|
||||
pub gid: u32,
|
||||
+ pub groups: alloc::vec::Vec<u32>,
|
||||
}
|
||||
impl CallerCtx {
|
||||
pub fn filter_uid_gid(self, euid: u32, egid: u32) -> Self {
|
||||
@@ -785,6 +786,7 @@ impl CallerCtx {
|
||||
pid: self.pid,
|
||||
uid: euid,
|
||||
gid: egid,
|
||||
+ groups: self.groups,
|
||||
}
|
||||
} else {
|
||||
self
|
||||
@@ -0,0 +1,112 @@
|
||||
diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs
|
||||
index 022f873..ab96dea 100644
|
||||
--- a/redox-rt/src/signal.rs
|
||||
+++ b/redox-rt/src/signal.rs
|
||||
@@ -1,4 +1,10 @@
|
||||
-use core::{ffi::c_int, ptr::NonNull, sync::atomic::Ordering};
|
||||
+use core::{
|
||||
+ ffi::c_int,
|
||||
+ hint::unreachable_unchecked,
|
||||
+ panic::AssertUnwindSafe,
|
||||
+ ptr::NonNull,
|
||||
+ sync::atomic::Ordering,
|
||||
+};
|
||||
|
||||
use syscall::{
|
||||
CallFlags, EAGAIN, EINTR, EINVAL, ENOMEM, EPERM, Error, RawAction, Result, SenderInfo,
|
||||
@@ -103,6 +109,47 @@ pub struct SiginfoAbi {
|
||||
pub si_value: usize, // sigval
|
||||
}
|
||||
|
||||
+fn invoke_signal_handler<F: FnOnce()>(f: AssertUnwindSafe<F>) -> bool {
|
||||
+ fn do_call<F: FnOnce()>(data: *mut u8) {
|
||||
+ let callback = unsafe { &mut *data.cast::<Option<AssertUnwindSafe<F>>>() };
|
||||
+ if let Some(callback) = callback.take() {
|
||||
+ callback.0();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ fn do_catch<F: FnOnce()>(_data: *mut u8, _payload: *mut u8) {}
|
||||
+
|
||||
+ let mut callback = Some(f);
|
||||
+ unsafe {
|
||||
+ core::intrinsics::catch_unwind(
|
||||
+ do_call::<F>,
|
||||
+ (&mut callback as *mut Option<AssertUnwindSafe<F>>).cast(),
|
||||
+ do_catch::<F>,
|
||||
+ ) != 0
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+#[inline(always)]
|
||||
+unsafe fn return_ignored_signal(
|
||||
+ os: &RtTcb,
|
||||
+ stack: &SigStack,
|
||||
+ signals_were_disabled: bool,
|
||||
+) {
|
||||
+ unsafe {
|
||||
+ (*os.arch.get()).last_sig_was_restart = true;
|
||||
+ (*os.arch.get()).last_sigstack = NonNull::new(stack.link);
|
||||
+ }
|
||||
+
|
||||
+ if !signals_were_disabled {
|
||||
+ core::sync::atomic::compiler_fence(Ordering::Release);
|
||||
+ let control_flags = &os.control.control_flags;
|
||||
+ control_flags.store(
|
||||
+ control_flags.load(Ordering::Relaxed) & !SigcontrolFlags::INHIBIT_DELIVERY.bits(),
|
||||
+ Ordering::Relaxed,
|
||||
+ );
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
#[inline(always)]
|
||||
unsafe fn inner(stack: &mut SigStack) {
|
||||
let os = unsafe { &Tcb::current().unwrap().os_specific };
|
||||
@@ -168,7 +215,10 @@ unsafe fn inner(stack: &mut SigStack) {
|
||||
// and reaching this code. If so, we do already know whether the signal is IGNORED *now*,
|
||||
// and so we should return early ideally without even temporarily touching the signal mask.
|
||||
SigactionKind::Ignore => {
|
||||
- panic!("ctl {:#x?} signal {}", os.control, stack.sig_num)
|
||||
+ unsafe {
|
||||
+ return_ignored_signal(os, stack, signals_were_disabled);
|
||||
+ }
|
||||
+ return;
|
||||
}
|
||||
// this case should be treated equally as the one above
|
||||
//
|
||||
@@ -183,7 +233,9 @@ unsafe fn inner(stack: &mut SigStack) {
|
||||
CallFlags::empty(),
|
||||
&[ProcCall::Exit as u64, u64::from(sig) << 8],
|
||||
);
|
||||
- panic!()
|
||||
+ // SAFETY: ProcCall::Exit terminates the current process when it succeeds, so reaching
|
||||
+ // this point would violate the proc manager exit contract.
|
||||
+ unsafe { unreachable_unchecked() }
|
||||
}
|
||||
SigactionKind::Handled { handler } => handler,
|
||||
};
|
||||
@@ -224,15 +276,21 @@ unsafe fn inner(stack: &mut SigStack) {
|
||||
si_uid: sender_uid as i32,
|
||||
si_value: stack.sival,
|
||||
};
|
||||
- unsafe {
|
||||
+ if invoke_signal_handler(AssertUnwindSafe(|| unsafe {
|
||||
sigaction(
|
||||
stack.sig_num as c_int,
|
||||
core::ptr::addr_of!(info).cast(),
|
||||
stack as *mut SigStack as *mut (),
|
||||
)
|
||||
- };
|
||||
+ })) {
|
||||
+ let _ = syscall::write(2, b"redox-rt: sa_siginfo handler panicked; continuing\n");
|
||||
+ }
|
||||
} else if let Some(handler) = unsafe { handler.handler } {
|
||||
- handler(stack.sig_num as c_int);
|
||||
+ if invoke_signal_handler(AssertUnwindSafe(|| {
|
||||
+ handler(stack.sig_num as c_int);
|
||||
+ })) {
|
||||
+ let _ = syscall::write(2, b"redox-rt: sa_handler panicked; continuing\n");
|
||||
+ }
|
||||
}
|
||||
|
||||
// Disable signals while we modify the sigmask again
|
||||
@@ -0,0 +1,101 @@
|
||||
diff --git a/src/start.rs b/src/start.rs
|
||||
--- a/src/start.rs
|
||||
+++ b/src/start.rs
|
||||
@@ -1,10 +1,7 @@
|
||||
//! Startup code.
|
||||
|
||||
use alloc::{boxed::Box, vec::Vec};
|
||||
-use core::{intrinsics, ptr};
|
||||
-
|
||||
-#[cfg(target_os = "redox")]
|
||||
-use generic_rt::ExpectTlsFree;
|
||||
+use core::{fmt::Write, intrinsics, panic::AssertUnwindSafe, ptr};
|
||||
|
||||
use crate::{
|
||||
ALLOCATOR,
|
||||
@@ -143,6 +141,29 @@ fn io_init() {
|
||||
stdio::stderr = stdio::default_stderr().get();
|
||||
}
|
||||
}
|
||||
+
|
||||
+fn catch_unwind<F: FnOnce()>(f: AssertUnwindSafe<F>) -> Result<(), ()> {
|
||||
+ fn do_call<F: FnOnce()>(data: *mut u8) {
|
||||
+ let callback = unsafe { &mut *data.cast::<Option<AssertUnwindSafe<F>>>() };
|
||||
+ if let Some(callback) = callback.take() {
|
||||
+ callback.0();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ fn do_catch<F: FnOnce()>(_data: *mut u8, _payload: *mut u8) {}
|
||||
+
|
||||
+ let mut callback = Some(f);
|
||||
+ let panicked = unsafe {
|
||||
+ intrinsics::catch_unwind(
|
||||
+ do_call::<F>,
|
||||
+ (&mut callback as *mut Option<AssertUnwindSafe<F>>).cast(),
|
||||
+ do_catch::<F>,
|
||||
+ ) != 0
|
||||
+ };
|
||||
+
|
||||
+ if panicked { Err(()) } else { Ok(()) }
|
||||
+}
|
||||
+
|
||||
#[cold]
|
||||
fn abort_startup(args: core::fmt::Arguments<'_>) -> ! {
|
||||
let mut w = platform::FileWriter::new(2);
|
||||
@@ -164,14 +184,23 @@ pub unsafe extern "C" fn relibc_start_v1(
|
||||
unsafe { relibc_verify_host() };
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
- let thr_fd = redox_rt::proc::FdGuard::new(
|
||||
- unsafe {
|
||||
- crate::platform::get_auxv_raw(sp.auxv().cast(), redox_rt::auxv_defs::AT_REDOX_THR_FD)
|
||||
- }
|
||||
- .expect_notls("no thread fd present"),
|
||||
- )
|
||||
- .to_upper()
|
||||
- .expect_notls("failed to move thread fd to upper table");
|
||||
+ let thr_fd = {
|
||||
+ let thr_fd = match unsafe {
|
||||
+ crate::platform::get_auxv_raw(sp.auxv().cast(), redox_rt::auxv_defs::AT_REDOX_THR_FD)
|
||||
+ } {
|
||||
+ Some(thr_fd) => thr_fd,
|
||||
+ None => abort_startup(format_args!(
|
||||
+ "relibc_start_v1: missing AT_REDOX_THR_FD auxv entry; no thread fd present\n"
|
||||
+ )),
|
||||
+ };
|
||||
+
|
||||
+ match redox_rt::proc::FdGuard::new(thr_fd).to_upper() {
|
||||
+ Ok(thr_fd) => thr_fd,
|
||||
+ Err(err) => abort_startup(format_args!(
|
||||
+ "relibc_start_v1: failed to move thread fd to upper table: {err:?}\n"
|
||||
+ )),
|
||||
+ }
|
||||
+ };
|
||||
|
||||
// Initialize TLS, if necessary
|
||||
unsafe {
|
||||
@@ -237,7 +266,10 @@ pub unsafe extern "C" fn relibc_start_v1(
|
||||
let mut f = unsafe { &__preinit_array_start } as *const _;
|
||||
#[allow(clippy::op_ref)]
|
||||
while f < &raw const __preinit_array_end {
|
||||
- (unsafe { *f })();
|
||||
+ let func = unsafe { *f };
|
||||
+ if catch_unwind(AssertUnwindSafe(|| unsafe { (*f)() })).is_err() {
|
||||
+ log_initializer_panic(".preinit_array", func);
|
||||
+ }
|
||||
f = unsafe { f.offset(1) };
|
||||
}
|
||||
}
|
||||
@@ -247,7 +279,10 @@ pub unsafe extern "C" fn relibc_start_v1(
|
||||
let mut f = unsafe { &__init_array_start } as *const _;
|
||||
#[allow(clippy::op_ref)]
|
||||
while f < &raw const __init_array_end {
|
||||
- (unsafe { *f })();
|
||||
+ let func = unsafe { *f };
|
||||
+ if catch_unwind(AssertUnwindSafe(|| unsafe { (*f)() })).is_err() {
|
||||
+ log_initializer_panic(".init_array", func);
|
||||
+ }
|
||||
f = unsafe { f.offset(1) };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user