From 33596e84f6445101a5b41c661f241b55602b1f9f Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 26 Jan 2025 21:22:03 +0000 Subject: [PATCH] Updating repo --- 611/404.html | 1765 ++++ .../index.html | 1970 ++++ 611/Community_Forums/index.html | 1822 ++++ 611/Community_Github/index.html | 1934 ++++ 611/Community_IRC/index.html | 1986 ++++ 611/Contribute/Armbian-config/index.html | 2232 +++++ .../index.html | 1810 ++++ 611/Developer-Guide_Build-Commands/index.html | 1980 ++++ .../index.html | 1984 ++++ 611/Developer-Guide_Build-Switches/index.html | 2243 +++++ .../index.html | 1953 ++++ .../index.html | 1925 ++++ .../index.html | 2308 +++++ 611/Developer-Guide_Extensions/index.html | 2030 +++++ 611/Developer-Guide_Overview/index.html | 1964 ++++ .../index.html | 1947 ++++ 611/Developer-Guide_Welcome/index.html | 1888 ++++ .../index.html | 1858 ++++ 611/Mirrors/index.html | 2406 +++++ 611/Process_Armbian-Task-Tracking/index.html | 1857 ++++ 611/Process_CI/index.html | 2346 +++++ 611/Process_Contribute/index.html | 1979 ++++ 611/Process_Managing_Workflow/index.html | 1843 ++++ 611/Process_Release-Model/index.html | 2291 +++++ 611/Quick_facts/index.html | 1831 ++++ 611/Release_Board-Maintainers/index.html | 1844 ++++ 611/Release_Changelog/index.html | 8005 +++++++++++++++++ 611/User-Guide_Advanced-Features/index.html | 2253 +++++ .../Localisation/index.html | 1921 ++++ .../Network/index.html | 2049 +++++ .../System/index.html | 2707 ++++++ 611/User-Guide_Armbian-Config/index.html | 1920 ++++ .../Containers/index.html | 2002 +++++ .../DNS/index.html | 1945 ++++ .../Database/index.html | 2022 +++++ .../Desktops/index.html | 1874 ++++ .../DevTools/index.html | 1889 ++++ .../Downloaders/index.html | 2838 ++++++ .../HomeAutomation/index.html | 2039 +++++ .../Management/index.html | 1925 ++++ .../Media/index.html | 2261 +++++ .../Monitoring/index.html | 2076 +++++ .../Music/index.html | 1905 ++++ .../Netconfig/index.html | 1985 ++++ .../Printing/index.html | 1938 ++++ .../WebHosting/index.html | 1954 ++++ 611/User-Guide_Armbian-Software/index.html | 1880 ++++ 611/User-Guide_Armbian_overlays/index.html | 2176 +++++ 611/User-Guide_Autoconfig/index.html | 2120 +++++ .../index.html | 2137 +++++ 611/User-Guide_Board-Support-Rules/index.html | 2066 +++++ 611/User-Guide_FAQ/index.html | 2162 +++++ 611/User-Guide_Fine-Tuning/index.html | 2228 +++++ 611/User-Guide_Getting-Started/index.html | 2315 +++++ 611/User-Guide_Networking/index.html | 2174 +++++ 611/User-Guide_Recovery/index.html | 2016 +++++ 611/assets/images/favicon.png | Bin 0 -> 1870 bytes 611/assets/javascripts/bundle.60a45f97.min.js | 16 + .../javascripts/bundle.60a45f97.min.js.map | 7 + .../javascripts/lunr/min/lunr.ar.min.js | 1 + .../javascripts/lunr/min/lunr.da.min.js | 18 + .../javascripts/lunr/min/lunr.de.min.js | 18 + .../javascripts/lunr/min/lunr.du.min.js | 18 + .../javascripts/lunr/min/lunr.el.min.js | 1 + .../javascripts/lunr/min/lunr.es.min.js | 18 + .../javascripts/lunr/min/lunr.fi.min.js | 18 + .../javascripts/lunr/min/lunr.fr.min.js | 18 + .../javascripts/lunr/min/lunr.he.min.js | 1 + .../javascripts/lunr/min/lunr.hi.min.js | 1 + .../javascripts/lunr/min/lunr.hu.min.js | 18 + .../javascripts/lunr/min/lunr.hy.min.js | 1 + .../javascripts/lunr/min/lunr.it.min.js | 18 + .../javascripts/lunr/min/lunr.ja.min.js | 1 + .../javascripts/lunr/min/lunr.jp.min.js | 1 + .../javascripts/lunr/min/lunr.kn.min.js | 1 + .../javascripts/lunr/min/lunr.ko.min.js | 1 + .../javascripts/lunr/min/lunr.multi.min.js | 1 + .../javascripts/lunr/min/lunr.nl.min.js | 18 + .../javascripts/lunr/min/lunr.no.min.js | 18 + .../javascripts/lunr/min/lunr.pt.min.js | 18 + .../javascripts/lunr/min/lunr.ro.min.js | 18 + .../javascripts/lunr/min/lunr.ru.min.js | 18 + .../javascripts/lunr/min/lunr.sa.min.js | 1 + .../lunr/min/lunr.stemmer.support.min.js | 1 + .../javascripts/lunr/min/lunr.sv.min.js | 18 + .../javascripts/lunr/min/lunr.ta.min.js | 1 + .../javascripts/lunr/min/lunr.te.min.js | 1 + .../javascripts/lunr/min/lunr.th.min.js | 1 + .../javascripts/lunr/min/lunr.tr.min.js | 18 + .../javascripts/lunr/min/lunr.vi.min.js | 1 + .../javascripts/lunr/min/lunr.zh.min.js | 1 + 611/assets/javascripts/lunr/tinyseg.js | 206 + 611/assets/javascripts/lunr/wordcut.js | 6708 ++++++++++++++ .../workers/search.f8cc74c7.min.js | 42 + .../workers/search.f8cc74c7.min.js.map | 7 + 611/assets/stylesheets/main.a40c8224.min.css | 1 + .../stylesheets/main.a40c8224.min.css.map | 1 + .../stylesheets/palette.06af60db.min.css | 1 + .../stylesheets/palette.06af60db.min.css.map | 1 + 611/css/armbian-extra.css | 7 + 611/css/dashicons.min.css | 1 + 611/css/maxmegamenu.js | 357 + 611/css/style(1).css | 773 ++ 611/images/BAZ001.png | Bin 0 -> 8396 bytes 611/images/CINNAMON01.png | Bin 0 -> 288613 bytes 611/images/CON001.webp | Bin 0 -> 10436 bytes 611/images/CON004.webp | Bin 0 -> 115608 bytes 611/images/CON005.webp | Bin 0 -> 34377 bytes 611/images/CON007.png | Bin 0 -> 36798 bytes 611/images/DAT001.png | Bin 0 -> 12751 bytes 611/images/DAT005.png | Bin 0 -> 12079 bytes 611/images/DE31.png | Bin 0 -> 288613 bytes 611/images/DEL001.png | Bin 0 -> 12509 bytes 611/images/DNS001.png | Bin 0 -> 5197 bytes 611/images/DOW001.png | Bin 0 -> 22398 bytes 611/images/DOW003.png | Bin 0 -> 12509 bytes 611/images/DOW005.png | Bin 0 -> 309464 bytes 611/images/DOW011.png | Bin 0 -> 20040 bytes 611/images/DOW013.png | Bin 0 -> 8141 bytes 611/images/DOW015.png | Bin 0 -> 36649 bytes 611/images/DOW017.png | Bin 0 -> 4249 bytes 611/images/DOW019.png | Bin 0 -> 8396 bytes 611/images/DOW021.png | Bin 0 -> 24413 bytes 611/images/DOW023.png | Bin 0 -> 5177 bytes 611/images/DOW025.png | Bin 0 -> 26425 bytes 611/images/DOW040.png | Bin 0 -> 46333 bytes 611/images/GRA001.png | Bin 0 -> 23060 bytes 611/images/HA001.png | Bin 0 -> 99894 bytes 611/images/HA003.png | Bin 0 -> 52868 bytes 611/images/HAS001.png | Bin 0 -> 52868 bytes 611/images/JEL001.png | Bin 0 -> 46333 bytes 611/images/LID001.png | Bin 0 -> 24413 bytes 611/images/MAN001.png | Bin 0 -> 507350 bytes 611/images/MAN005.png | Bin 0 -> 9840 bytes 611/images/MED001.png | Bin 0 -> 8141 bytes 611/images/MED003.png | Bin 0 -> 4931 bytes 611/images/MED010.png | Bin 0 -> 8860 bytes 611/images/MED015.png | Bin 0 -> 13497 bytes 611/images/MED020.png | Bin 0 -> 10024 bytes 611/images/MED927.png | Bin 0 -> 7634 bytes 611/images/MON005.png | Bin 0 -> 57352 bytes 611/images/OCT001.png | Bin 0 -> 17884 bytes 611/images/RAD001.png | Bin 0 -> 4249 bytes 611/images/RDR001.png | Bin 0 -> 5177 bytes 611/images/SABN01.png | Bin 0 -> 20040 bytes 611/images/SON001.png | Bin 0 -> 36649 bytes 611/images/SSH200.png | Bin 0 -> 28726 bytes 611/images/SW25.webp | Bin 0 -> 10436 bytes 611/images/SWAG01.png | Bin 0 -> 107871 bytes 611/images/SY018.png | Bin 0 -> 50477 bytes 611/images/TRA001.png | Bin 0 -> 309464 bytes 611/images/WG001.png | Bin 0 -> 14166 bytes 611/images/WTC001.png | Bin 0 -> 36798 bytes 611/images/a1-logo.png | Bin 0 -> 13076 bytes 611/images/a2-logo.png | Bin 0 -> 16090 bytes 611/images/armbian-config-1.png | Bin 0 -> 32454 bytes 611/images/armbian-config-10.png | Bin 0 -> 27618 bytes 611/images/armbian-config-2.png | Bin 0 -> 27524 bytes 611/images/armbian-config-3.png | Bin 0 -> 30548 bytes 611/images/armbian-config-4.png | Bin 0 -> 16083 bytes 611/images/armbian-config-5.png | Bin 0 -> 31221 bytes 611/images/armbian-config-6.png | Bin 0 -> 22243 bytes 611/images/armbian-config-7.png | Bin 0 -> 35051 bytes 611/images/armbian-config-8.png | Bin 0 -> 36084 bytes 611/images/armbian-config-9.png | Bin 0 -> 17293 bytes 611/images/banana-i2c-display1.jpg | Bin 0 -> 30566 bytes 611/images/banana-spi-display.jpg | Bin 0 -> 39690 bytes 611/images/betaimages.png | Bin 0 -> 10578 bytes 611/images/budgie.png | Bin 0 -> 335251 bytes 611/images/build-all-images.png | Bin 0 -> 21193 bytes 611/images/build-images-ci.png | Bin 0 -> 9255 bytes 611/images/build-selected-blured.png | Bin 0 -> 36055 bytes 611/images/build-single-clean.png | Bin 0 -> 14275 bytes 611/images/build-train.png | Bin 0 -> 11523 bytes 611/images/buildselected.png | Bin 0 -> 26064 bytes 611/images/cinnamon.png | Bin 0 -> 288613 bytes 611/images/commit-changes.png | Bin 0 -> 2787 bytes ...plete-artifact-matrix-standard-support.png | Bin 0 -> 26928 bytes 611/images/create-pull-reqest.png | Bin 0 -> 2869 bytes 611/images/dedicated-applications.png | Bin 0 -> 174489 bytes 611/images/edit-connection.png | Bin 0 -> 23165 bytes 611/images/edit-icon.png | Bin 0 -> 950 bytes 611/images/forums.png | Bin 0 -> 498869 bytes 611/images/jira-dark-revised.png | Bin 0 -> 216514 bytes 611/images/kanban.png | Bin 0 -> 227174 bytes 611/images/linterror.png | Bin 0 -> 20381 bytes 611/images/loginprompt.png | Bin 0 -> 71325 bytes 611/images/logo.png | Bin 0 -> 23190 bytes 611/images/logo.svg | 138 + 611/images/logo_middle.png | Bin 0 -> 3342 bytes 611/images/lvdsbanana.png | Bin 0 -> 134139 bytes 611/images/mr-pipeline.png | Bin 0 -> 98348 bytes 611/images/product-backlog-structure.png | Bin 0 -> 11916 bytes 611/images/propose-changes.png | Bin 0 -> 45639 bytes 611/images/rolling-releases.png | Bin 0 -> 101758 bytes 611/images/run-worflow-button.png | Bin 0 -> 2816 bytes 611/images/run-workflow.png | Bin 0 -> 3660 bytes 611/images/sandisk-extreme-a2.png | Bin 0 -> 22584 bytes 611/images/sandisk-extremepro-a1.png | Bin 0 -> 22884 bytes 611/images/sandisk-ultra-a1.png | Bin 0 -> 20830 bytes 611/images/selected-images.png | Bin 0 -> 6767 bytes 611/images/smoke-tests.png | Bin 0 -> 15456 bytes 611/images/stable-images.png | Bin 0 -> 6224 bytes 611/images/standard-support-images.png | Bin 0 -> 133217 bytes 611/images/taskProcess1.png | Bin 0 -> 97946 bytes 611/images/taskProcess2.png | Bin 0 -> 80153 bytes 611/images/taskProcess3.png | Bin 0 -> 112552 bytes 611/images/taskProcess4.png | Bin 0 -> 137147 bytes 611/images/wait-for-preview.png | Bin 0 -> 11932 bytes 611/images/wifi-connect.png | Bin 0 -> 6426 bytes 611/images/xfce.png | Bin 0 -> 234424 bytes 611/index.html | 2100 +++++ 611/search/search_index.json | 1 + 611/sitemap.xml | 227 + 611/sitemap.xml.gz | Bin 0 -> 740 bytes 215 files changed, 131659 insertions(+) create mode 100644 611/404.html create mode 100644 611/Board_Maintainers_Procedures_and_Guidelines/index.html create mode 100644 611/Community_Forums/index.html create mode 100644 611/Community_Github/index.html create mode 100644 611/Community_IRC/index.html create mode 100644 611/Contribute/Armbian-config/index.html create mode 100644 611/Developer-Guide_Adding-Board-Family/index.html create mode 100644 611/Developer-Guide_Build-Commands/index.html create mode 100644 611/Developer-Guide_Build-Preparation/index.html create mode 100644 611/Developer-Guide_Build-Switches/index.html create mode 100644 611/Developer-Guide_Building-with-Docker/index.html create mode 100644 611/Developer-Guide_Building-with-Multipass/index.html create mode 100644 611/Developer-Guide_Extensions-Hooks/index.html create mode 100644 611/Developer-Guide_Extensions/index.html create mode 100644 611/Developer-Guide_Overview/index.html create mode 100644 611/Developer-Guide_User-Configurations/index.html create mode 100644 611/Developer-Guide_Welcome/index.html create mode 100644 611/Development-Code_Review_Procedures_and_Guidelines/index.html create mode 100644 611/Mirrors/index.html create mode 100644 611/Process_Armbian-Task-Tracking/index.html create mode 100644 611/Process_CI/index.html create mode 100644 611/Process_Contribute/index.html create mode 100644 611/Process_Managing_Workflow/index.html create mode 100644 611/Process_Release-Model/index.html create mode 100644 611/Quick_facts/index.html create mode 100644 611/Release_Board-Maintainers/index.html create mode 100644 611/Release_Changelog/index.html create mode 100644 611/User-Guide_Advanced-Features/index.html create mode 100644 611/User-Guide_Armbian-Config/Localisation/index.html create mode 100644 611/User-Guide_Armbian-Config/Network/index.html create mode 100644 611/User-Guide_Armbian-Config/System/index.html create mode 100644 611/User-Guide_Armbian-Config/index.html create mode 100644 611/User-Guide_Armbian-Software/Containers/index.html create mode 100644 611/User-Guide_Armbian-Software/DNS/index.html create mode 100644 611/User-Guide_Armbian-Software/Database/index.html create mode 100644 611/User-Guide_Armbian-Software/Desktops/index.html create mode 100644 611/User-Guide_Armbian-Software/DevTools/index.html create mode 100644 611/User-Guide_Armbian-Software/Downloaders/index.html create mode 100644 611/User-Guide_Armbian-Software/HomeAutomation/index.html create mode 100644 611/User-Guide_Armbian-Software/Management/index.html create mode 100644 611/User-Guide_Armbian-Software/Media/index.html create mode 100644 611/User-Guide_Armbian-Software/Monitoring/index.html create mode 100644 611/User-Guide_Armbian-Software/Music/index.html create mode 100644 611/User-Guide_Armbian-Software/Netconfig/index.html create mode 100644 611/User-Guide_Armbian-Software/Printing/index.html create mode 100644 611/User-Guide_Armbian-Software/WebHosting/index.html create mode 100644 611/User-Guide_Armbian-Software/index.html create mode 100644 611/User-Guide_Armbian_overlays/index.html create mode 100644 611/User-Guide_Autoconfig/index.html create mode 100644 611/User-Guide_Basic-Troubleshooting/index.html create mode 100644 611/User-Guide_Board-Support-Rules/index.html create mode 100644 611/User-Guide_FAQ/index.html create mode 100644 611/User-Guide_Fine-Tuning/index.html create mode 100644 611/User-Guide_Getting-Started/index.html create mode 100644 611/User-Guide_Networking/index.html create mode 100644 611/User-Guide_Recovery/index.html create mode 100644 611/assets/images/favicon.png create mode 100644 611/assets/javascripts/bundle.60a45f97.min.js create mode 100644 611/assets/javascripts/bundle.60a45f97.min.js.map create mode 100644 611/assets/javascripts/lunr/min/lunr.ar.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.da.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.de.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.du.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.el.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.es.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.fi.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.fr.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.he.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.hi.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.hu.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.hy.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.it.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.ja.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.jp.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.kn.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.ko.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.multi.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.nl.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.no.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.pt.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.ro.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.ru.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.sa.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.stemmer.support.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.sv.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.ta.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.te.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.th.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.tr.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.vi.min.js create mode 100644 611/assets/javascripts/lunr/min/lunr.zh.min.js create mode 100644 611/assets/javascripts/lunr/tinyseg.js create mode 100644 611/assets/javascripts/lunr/wordcut.js create mode 100644 611/assets/javascripts/workers/search.f8cc74c7.min.js create mode 100644 611/assets/javascripts/workers/search.f8cc74c7.min.js.map create mode 100644 611/assets/stylesheets/main.a40c8224.min.css create mode 100644 611/assets/stylesheets/main.a40c8224.min.css.map create mode 100644 611/assets/stylesheets/palette.06af60db.min.css create mode 100644 611/assets/stylesheets/palette.06af60db.min.css.map create mode 100644 611/css/armbian-extra.css create mode 100644 611/css/dashicons.min.css create mode 100644 611/css/maxmegamenu.js create mode 100644 611/css/style(1).css create mode 100644 611/images/BAZ001.png create mode 100644 611/images/CINNAMON01.png create mode 100644 611/images/CON001.webp create mode 100644 611/images/CON004.webp create mode 100644 611/images/CON005.webp create mode 100644 611/images/CON007.png create mode 100644 611/images/DAT001.png create mode 100644 611/images/DAT005.png create mode 100644 611/images/DE31.png create mode 100644 611/images/DEL001.png create mode 100644 611/images/DNS001.png create mode 100644 611/images/DOW001.png create mode 100644 611/images/DOW003.png create mode 100644 611/images/DOW005.png create mode 100644 611/images/DOW011.png create mode 100644 611/images/DOW013.png create mode 100644 611/images/DOW015.png create mode 100644 611/images/DOW017.png create mode 100644 611/images/DOW019.png create mode 100644 611/images/DOW021.png create mode 100644 611/images/DOW023.png create mode 100644 611/images/DOW025.png create mode 100644 611/images/DOW040.png create mode 100644 611/images/GRA001.png create mode 100644 611/images/HA001.png create mode 100644 611/images/HA003.png create mode 100644 611/images/HAS001.png create mode 100644 611/images/JEL001.png create mode 100644 611/images/LID001.png create mode 100644 611/images/MAN001.png create mode 100644 611/images/MAN005.png create mode 100644 611/images/MED001.png create mode 100644 611/images/MED003.png create mode 100644 611/images/MED010.png create mode 100644 611/images/MED015.png create mode 100644 611/images/MED020.png create mode 100644 611/images/MED927.png create mode 100644 611/images/MON005.png create mode 100644 611/images/OCT001.png create mode 100644 611/images/RAD001.png create mode 100644 611/images/RDR001.png create mode 100644 611/images/SABN01.png create mode 100644 611/images/SON001.png create mode 100644 611/images/SSH200.png create mode 100644 611/images/SW25.webp create mode 100644 611/images/SWAG01.png create mode 100644 611/images/SY018.png create mode 100644 611/images/TRA001.png create mode 100644 611/images/WG001.png create mode 100644 611/images/WTC001.png create mode 100644 611/images/a1-logo.png create mode 100644 611/images/a2-logo.png create mode 100644 611/images/armbian-config-1.png create mode 100644 611/images/armbian-config-10.png create mode 100644 611/images/armbian-config-2.png create mode 100644 611/images/armbian-config-3.png create mode 100644 611/images/armbian-config-4.png create mode 100644 611/images/armbian-config-5.png create mode 100644 611/images/armbian-config-6.png create mode 100644 611/images/armbian-config-7.png create mode 100644 611/images/armbian-config-8.png create mode 100644 611/images/armbian-config-9.png create mode 100644 611/images/banana-i2c-display1.jpg create mode 100644 611/images/banana-spi-display.jpg create mode 100644 611/images/betaimages.png create mode 100644 611/images/budgie.png create mode 100644 611/images/build-all-images.png create mode 100644 611/images/build-images-ci.png create mode 100644 611/images/build-selected-blured.png create mode 100644 611/images/build-single-clean.png create mode 100644 611/images/build-train.png create mode 100644 611/images/buildselected.png create mode 100644 611/images/cinnamon.png create mode 100644 611/images/commit-changes.png create mode 100644 611/images/complete-artifact-matrix-standard-support.png create mode 100644 611/images/create-pull-reqest.png create mode 100644 611/images/dedicated-applications.png create mode 100644 611/images/edit-connection.png create mode 100644 611/images/edit-icon.png create mode 100644 611/images/forums.png create mode 100644 611/images/jira-dark-revised.png create mode 100644 611/images/kanban.png create mode 100644 611/images/linterror.png create mode 100644 611/images/loginprompt.png create mode 100644 611/images/logo.png create mode 100644 611/images/logo.svg create mode 100644 611/images/logo_middle.png create mode 100644 611/images/lvdsbanana.png create mode 100644 611/images/mr-pipeline.png create mode 100644 611/images/product-backlog-structure.png create mode 100644 611/images/propose-changes.png create mode 100644 611/images/rolling-releases.png create mode 100644 611/images/run-worflow-button.png create mode 100644 611/images/run-workflow.png create mode 100644 611/images/sandisk-extreme-a2.png create mode 100644 611/images/sandisk-extremepro-a1.png create mode 100644 611/images/sandisk-ultra-a1.png create mode 100644 611/images/selected-images.png create mode 100644 611/images/smoke-tests.png create mode 100644 611/images/stable-images.png create mode 100644 611/images/standard-support-images.png create mode 100644 611/images/taskProcess1.png create mode 100644 611/images/taskProcess2.png create mode 100644 611/images/taskProcess3.png create mode 100644 611/images/taskProcess4.png create mode 100644 611/images/wait-for-preview.png create mode 100644 611/images/wifi-connect.png create mode 100644 611/images/xfce.png create mode 100644 611/index.html create mode 100644 611/search/search_index.json create mode 100644 611/sitemap.xml create mode 100644 611/sitemap.xml.gz diff --git a/611/404.html b/611/404.html new file mode 100644 index 000000000..f16dc79c5 --- /dev/null +++ b/611/404.html @@ -0,0 +1,1765 @@ + + + + + + + + + + + + + + + + + + + + + + + Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ +

404 - Not found

+ +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/611/Board_Maintainers_Procedures_and_Guidelines/index.html b/611/Board_Maintainers_Procedures_and_Guidelines/index.html new file mode 100644 index 000000000..43b05fa4d --- /dev/null +++ b/611/Board_Maintainers_Procedures_and_Guidelines/index.html @@ -0,0 +1,1970 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Board Maintainers Procedures and Guidelines - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Board Maintainers Procedures and Guidelines

+ +

Board Maintainers Procedures and Guidelines

+

+ This topic should give you as new board maintainers a brief overview about what you should do, must do, and can do. What you as maintainer can expect from Armbian and what we expect from you. +

+ +

+

Requirements:

+

+ +

+ Even though you became a maintainer already just to make sure everything is set. +

+ +
    +
  • + You must have access to the hardware you applied to maintain +
  • +
  • + You must have a Github ID which should be listed in the documentation +
  • +
  • + You must have a forums account (you already have obviously) which should be listed in the documentation. If not let me know. +
  • +
  • You must have an Jira account and keep track of issues filed for your board
  • +
  • You must make sure Armbian Management has been informed of all of the above IDs for our documentation
  • +
  • + You should know Armbian basics like how to get an Armbian image run on your hardware and do basic debugging, ideally via serial console +
  • +
  • + Knowledge in development, writing code and so on is optional (but of course welcome ;-)) +
  • +
+ +

If you are a new maintainer, please make sure you have submitted your IDs and information using our maintainer registry form: Here

+

+

Maintaining:

+

+ +

+ So all requirements are met and you are a maintainer now. Now what? +

+ +

+ Maintainers must not necessarily be persons with development experience. They act as a intersection between end-users and the development team and serve the developers in best-effort manner. They are encouraged to answer basic/simple user questions (if possible, also best effort) without having to bother the development team. They are allowed to record bugs but are not allowed to escalate bugs. Team leaders do. +

+ +

+ Take note that it is still up to development team's discretion what gets attention since Armbian has to plan carefully how to spend its very limited resources. +

+ +
    +
  • + You must participate in release process:
    + Ideally you attend to the release meetings that usually happen four times a year about a month before release date (end of February, May, August, November). On that occasion you are given the chance to point out critical issues with your board. A typical agenda looks like this: https://docs.armbian.com/Process_Release-Model/#agenda
    +
    + However, while the meeting participation is optional you "must sign-off that device has been tested, is stable, and ready for release during release process". + This basically means you take the RC-images we provide and test them as best as you can for their functionality hardware-wise: +
      +
    • Does the board boot to both CLI and Desktop?
    • +
    • Is the desktop usable?
    • +
    • Does USB work? (at all or partially)
    • +
    • Other common use cases
    • +

    + If something does not work, this is fine also and totally normal. The important part is that it is documented and we get notified about the issues. + +During each release you will be expected to fill out the following form: Release Testing Form +
  • +
+
    +
  • + You should follow the commit history on Github. For once you may learn something about how things work both development-wise and behind the scenes in general and also may notice changes that affect the hardware/board you are dealing with. +
  • +
  • + While not required, you should have a build environment setup so you can build images with the most recent images and test them right away. Your feedback, either positive or negative, is very welcome. You are free to add comments to every commit and pull request. +
    +
    + Ideally you have multiple microSD cards laying around to test regular updates on current releases and nightly without having to re-flash the same card every time to switch between branches.

    + Alternatively you can grab auto-built images from the build train once available: https://github.com/armbian/build/releases

    + Take note that the building process takes quite a while so you might be faster using your own build environment. +
  • +
+ +
    +
  • + You must provide "best effort" support in the forum:
    + Do not let that wording intimidate you. This is not a complicated task. Regarding forums this can include things like +
      +
    • + answering obvious questions (for example by pointing to our documentation, ideally directly to the solution page), +
    • +
    • + let the questioner know that additional information is needed for further debugging (e.g. request "armbianmonitor -u" output) or +
    • +
    • + for upgrade issues, ask if they can recreate the issue with a fresh untouched image from: https://www.armbian.com/download/ +
    • +
    • If you need additional direction on dealing with an issue contact Werner on the forums or Discord.
    • +
    +
  • +
+
    +
  • + You must provide "best effort" support in Jira:
    +
      +
    • + Review submitted issues for you board made by Armbian's contributors +
    • +
    • + For upgrade issues, ask if they can recreate the issue with a fresh untouched image from: https://www.armbian.com/download/ +
    • +
    • If you have questions, concerns or are not sure about something, you can tag the issue for @Tenkawa or @TheLinuxBug to review
    • +
    +
  • +
+ +

+

Jira and Forum expectations:

+

+ +

Low priority issues are usually attended to and patched by the community. If the issue has existed for more than a release, you can create a Jira ticket for it. However the expectation is the issue will be low priority and may not be processed for some time. Issues such as, but not limited to, should be considered low priority:

+
    +
  • Wifi (this includes missing modules, AP mode, etc)
  • +
  • Bluetooth
  • +
  • GPIO
  • +
  • i2c
  • +
  • Hardware accelerators, including crypto or VPU (video acceleration)
  • +
  • DTB overlays (required for i2c devices, LCD displays, etc)
  • +
+ +

For high priority items you can create a Jira ticket so that when developers are able, they can process it. If you are going to create a Jira ticket, please be sure to collect as much information about the issue as possible first. If more information will be needed to process the issue, you should reply to the user asking for that additional information and make sure it is included in the ticket. Issues like these should be considered a higher priority:

+
    +
  • Image does not boot
  • +
  • Image is corrupt
  • +
  • Packages in the image are corrupt
  • +
  • SDcard or eMMc support is not functioning as expected
  • +
+ +

What should you do if you run into an issue on the forum?

+
    +
  • If the issues is affecting a lot of people, you can create a Jira ticket for the issue to make sure it is reported and seen by developers.
  • +
  • If you report an issue and you feel it is important, after 8 weeks you can tag (@Tenkawa) in an reply to the ticket and ask for him to review.
  • +
  • If the issue is important it will be directed to management. If it is deemed not important, you will get a reply stating that we do not have a timeline for the fix and that it will be handled by volunteers when/if possible.
  • +
+ +

What should you do if there is a long standing Jira ticket?

+
    +
  • If you see an issue and you feel it is important, after 8 weeks you can tag (@Tenkawa) in an reply to the ticket and ask for him to review.
  • +
  • If the issue is important it will be directed to management, if it is deemed not important, you will get a reply stating that we don't have a timeline for the fix and that it will be handled by volunteers when possible.
  • +
+

+

Losing support status:

+

+

+ As mentioned in the board support rules the support status of a board will be revoked for at least the current and upcoming release cycle(s) if a "must" of the Maintaining section above is not fulfilled. +

+ +

+ As an example: August 30th is release date for 22.08 release, sign-off dead line is 21th. If maintainer misses the RC sign-off window the board is demoted to CSC for both 22.08 and 22.11 releases. +

+ +

+ The development team may grant exceptions on their discretion. +

+ +

+

Armbian's assistance:

+

+ +

If you have questions about maintainer-ship or want to learn more deeper insights about the build framework and such Armbian will provide you with all information in best-effort. If time allows we can explain and teach you personally various aspects about the project. Otherwise, if you want to learn more about the build framework, dive in, play with it and read the documenenation. Also if you have other concerns please do not hesitate to reach out via forums, IRC or Discord. Armbian cares about the people who care about Armbian  :)

+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/611/Community_Forums/index.html b/611/Community_Forums/index.html new file mode 100644 index 000000000..6668fdc83 --- /dev/null +++ b/611/Community_Forums/index.html @@ -0,0 +1,1822 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Forums - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+ +
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/611/Community_Github/index.html b/611/Community_Github/index.html new file mode 100644 index 000000000..5df364bca --- /dev/null +++ b/611/Community_Github/index.html @@ -0,0 +1,1934 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Github - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Main project repositories

+

Armbian Build

+

armbian/build

+

Framework can build generic Armbian or custom Linux image.

+

Armbian Config

+

armbian/configng

+

Utility for configuring:

+
    +
  • hardware,
  • +
  • adjusting services,
  • +
  • installing applications.
  • +
+

Armbian OS

+

armbian/os

+

Armbian OS assembly line:

+ +

Armbian Community

+

armbian/community

+

Armbian OS community assembly line:

+ +

Armbian Distribution

+

armbian/distribution

+

Armbian OS with pre-installed applications:

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/611/Community_IRC/index.html b/611/Community_IRC/index.html new file mode 100644 index 000000000..8f80d3a29 --- /dev/null +++ b/611/Community_IRC/index.html @@ -0,0 +1,1986 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Armbian Social Media Channels - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Social media

+

Armbian on X and Mastodon

+

Armbian short announcements are done via 𝕏 (formerly known as Twitter): https://twitter.com/armbian and https://fosstodon.org/@armbian

+

IRC Channel / Discord / Matrix

+

👏 Overview

+

As announced in the forums everyone interested can communicate in realtime using the internet relay chat (or IRC for short). +Well known IRC clients for CLI are Weechat or Irssi and for GUI Hexchat or Konversation.
+Mature clients for Matrix: Element or FluffyChat.

+

Besides that communication is also possible via Discord or Matrix (closed beta).

+

🔌 How to connect

+

IRC

+

Libera network:

+
    +
  • Server: irc.libera.chat
  • +
  • Ports: 6697 / non-encrypted: 6667
  • +
  • Channels: as listed below
  • +
+

OFTC network:

+
    +
  • Server: irc.oftc.net
  • +
  • Ports: 6697 / non-encrypted: 6667
  • +
  • Channels: #armbian and #armbian-announcements are available only
  • +
+

In order to enter main #armbian channels registration with Nickserv is mandatory on Libera. Check Libera Chat documentation for further information.

+

Discord

+

Simply click here: https://discord.com/invite/armbian

+

Channels starting with #armbian- are relayed between Discord and Libera IRC so it does not matter if you join IRC or Discord as both ends receive your messages. Check #welcome-and-rules for more information. +The main #armbian channel and #armbian-announcements are relayed between Discord, Libera, OFTC and Matrix.

+

Matrix (closed beta)

+
    +
  • Server: matrix.armbian.com
  • +
  • Channels: #armbian:matrix.armbian.com and #armbian-announcements:matrix.armbian.com are available only
  • +
  • To receive an invitation for former please ping either Lanefu or Werner with your Matrix handle in any known ways to communicate like the chat options above or forums. Once in feel free to invite others by yourself.
  • +
+

🛑 Rules

+

Forums registration terms and rules apply for our chats: https://forum.armbian.com/terms

+

💬 Channels (depending on platform only a limited selection might be available)

+
    +
  • #armbian is the project’s main channel. Issue tracking, peer-to-peer user support or upcoming release planning talks.
  • +
  • #armbian-announcements : important messages from the Armbian team. You definitely want to idle here. Moderated channel
  • +
  • #armbian-devel : build engine development topics
  • +
  • #armbian-desktop : desktop environment development
  • +
  • #armbian-csc unsupported/stating board talk
  • +
  • #armbian-allwinner Allwinner-related SoC talk
  • +
  • #armbian-amlogic Amlogic-related SoC talk
  • +
  • #armbian-broadcom Broadcom-related SoC talk
  • +
  • #armbian-rockchip Rockchip-related SoC talk
  • +
  • #armbian-offtopic General chit chat, whatever that does not fit other channels
  • +
  • #armbian-commits Whenever a new interaction with a repository on Github happens it will be announced. Moderated channel
  • +
+

👮 Services

+

Besides the services offered by IRC (like Nickserv or Chanserv) Armbian has set up some own services (on Libera only).

+

ArmbianGithub

+
    +
  • Has the purpose to fill #armbian-commits channel
  • +
+

DC-IRC

+
    +
  • Has the purpose to relay messages between the IRC networks and Discord. Applies for all channels beginning with #armbian- as well as #armbian.
  • +
+

ArmbianHelper

+
    +
  • Allows searching forums via Google API (not very precise though)
      +
    • Example: ,g Allwinner H6 panfrost
    • +
    +
  • +
  • A few more minor commands, mostly used by staff or do not need introduction
      +
    • .nonprofit, .sed, .contribute, .rtfm, .fortune, .sunxi, .meson, help, help irc, .tvboxes
    • +
    +
  • +
  • Translation for non-native English speakers
      +
    • Simply start your sentence with -- at the beginning and the bot will translate your message regardless of the source language into English.
      +Note: This services will be activated manually on demand (like planned meetings for example) since its backend generates cost.
    • +
    +
  • +
+

❔ FAQ

+
    +
  • Why are there so many people in the channel and nobody is talking?
      +
    • It is pretty common for community IRC channels for people to simply idle there. Many also using so called IRC bouncers https://en.wikipedia.org/wiki/BNC_(software) that keeps their connection to the channel alive to act like an answering machine.
    • +
    +
  • +
+
    +
  • I wrote ‘Hi’ but nobody answered. How do I get support there?
      +
    • Probably there is nobody around at the time. Keep in mind that all users are spread around the globe and therefore living in many different time zones.
      +It is a common habit to simply state your question or issue and then wait patiently for an answer. Depending how complex this may take up to a few hours because most Armbian contributors have detailed knowledge in a specific board family only.
    • +
    +
  • +
  • Is the chat history public as well?
      +
    • Yes. All conversation is logged. These logs are open to the public. You can find them here: http://irc.armbian.com
    • +
    +
  • +
  • Why do some people have odd hostnames like @armbian/staff/lanefu or @user/username?
      +
    • These hostnames are so called project affiliation cloaks. These are meant to show a users affiliation to a specific project and their role there.
    • +
    +
  • +
  • Can I have that too?
      +
    • Yes. An Armbian affiliation cloak can be requested from Werner either via forums or IRC. They usually will be granted if you are a well known member in forums, a contributor via Github or donated to the project. Make sure you identified yourself to Nickserv beforehand.
    • +
    +
  • +
  • How can I protect my nickname so nobody can spoof me?
      +
    • Register your nick with Libera’s Nickserv service. Check https://libera.chat/guides/registration
      + Even though it is not mandatory you should register and identify with the services as other channels for example may not allow unregistered users to chat or join at all as anti-spam measure.
    • +
    +
  • +
  • Why do some users have voice (+v) in channel?
      +
    • As mentioned in forums “all contributors to the project, regardless if forums staff, contributor on Github or well known and longtime active user” may get voice on request.
    • +
    +
  • +
+
    +
  • Should I add away to my nick if I am AFK? Like Werner|away
      +
    • No. Please use the /away [reason] command as intended. For an explanation please have a look at the ZNC Wiki.
    • +
    +
  • +
+

👉 Bottom line

+

If you have any questions, comments regarding the IRC channels and/or services or found an issue in this documentation for think you can enhance it get in touch with Werner either via forums, IRC or Discord.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/611/Contribute/Armbian-config/index.html b/611/Contribute/Armbian-config/index.html new file mode 100644 index 000000000..4ea4bbfe1 --- /dev/null +++ b/611/Contribute/Armbian-config/index.html @@ -0,0 +1,2232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Armbian config - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Adding software title to Armbian config

+

Tinkering

+

Manual install

+

First try to install application manually. If it works on Debian or Ubuntu, proceed. In this example we will be using test.

+

Clone repository

+
Text Only
git clone https://github.com/armbian/configng
+
+

Design menu

+

Predict which commands you expect to have in the menu. For installing an application, we usually need two, install and uninstall. Armbian-config stores menu in JSON files, so you need to select appropriate file. +This one we will place under Software -> Management.

+
File location: tools/json/config.software.json
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
{
+    "id": "MAN005",
+    "description": "Webmin web-based management tool",
+    "command": [
+        "see_menu module_webmin"
+    ],
+    "status": "Stable",
+    "author": "@Tearran",
+    "condition": ""
+}
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Field nameFunctionNotes
idunique identifierSelect higher number. If you will select existing, application will fail to run
descriptionmenu descriptorThis will be displayed in the menu
promptconfirmation textSome features needs confirmation before proceeding
commandexecutes functionWhat should be run after we select and agree (optional)
statusStable|DisabledControl if function is shown to users in the menu
authorGitHub handleDeveloper or maintainer of this functionality
conditioncontrolling displayUnder what conditions we show this menu item
+
+

Note

+

Pay attention to JSON structure. JSON validator at pull request will break in case spaces or commas will be placed wrong.

+
+

Module code

+

Place module functions, each into its file, following by file naming convention, into one of the folders:

+
Folder location: tools/modules
1
+2
+3
+4
+5
+6
docs
+functions
+network
+runtime
+software
+system
+
+
File location: tools/template/module_software_template.sh
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
declare -A module_options
+module_options+=(
+    ["module_template,author"]="@armbian"
+    ["module_template,feature"]="module_template"
+    ["module_template,example"]="install remove help"
+    ["module_template,desc"]="Example module unattended interface."
+    ["module_template,status"]="review"
+)
+
+function module_template() {
+    local title="test"
+    local condition=$(which "$title" 2>/dev/null)
+
+    # Convert the example string to an array
+    local commands
+    IFS=' ' read -r -a commands <<< "${module_options["module_template,example"]}"
+
+    case "$1" in
+        "${commands[0]}")
+        echo "Installing $title..."
+        # Installation logic here
+        ;;
+        "${commands[1]}")
+        echo "Removing $title..."
+        # Removal logic here
+        ;;
+        "${commands[2]}")
+            echo -e "\nUsage: ${module_options["module_template,feature"]} <command>"
+            echo -e "Commands:  ${module_options["module_template,example"]}"
+            echo "Available commands:"
+            echo -e "\tinstall\t- Install $title."
+            echo -e "\tremove\t- Remove $title."
+            echo
+        ;;
+        *)
+        ${module_options["module_template,feature"]} ${commands[2]}
+        ;;
+    esac
+    }
+
+# uncomment to test the module
+#module_template "$1"
+
+
+

Note

+

Pay attention to coding style structure. If you use modern IDE, this will be done automatically.

+
+

Manual testing

+

Whenever you are making changes to the JSON or modules structure, make sure to join JSON segments into main JSON file and fun. This you do with a command: +

Python
tools/config-assemble.sh -p
+
+Python is required to run this tool.

+
Bash
sudo sudo bin/armbian-config --cmd
+
+

Unit tests

+

This part is optional but highly recommended for at least install functionality. Our CI infrastructure will test this feature at pull request, on general code changes (push to main branch) and daily. It will test feature on latest Debian and Ubuntu images. +Unit tests have simple design:

+

Name of the config file is function id (unique identifier) CON004.conf

+

File location: tests/CON004.conf
1
+2
+3
ENABLED=true
+RELEASE="bookworm:jammy:noble"
+CONDITION="test=\$(docker container ls -a |  grep portainer )"
+
+Make sure to add a test condition that makes sense. It has to return 0 when test succeeds and 1 if fails.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VariableFunctionDescription
ENABLEDfalse / trueIf test is live or not
PREINSTALLcmd to runspecific test dependencies
CONDITIONmain test verificationmust return 0 for test success
RELEASEbookworm:jammy:noble”run on specific or leave empty to run on all
+

Pull request

+

When your solution works locally and you prepare unit tests its time to submit a pull request. Fix your code and unit tests until all pull request checks becomes green.

+

Examples:

+ +

Documentation

+

Documentation is generated automatically after your pull request is merged. But as automated documentation might not be satisfactory, you can add cover image, header and footer. You can use markdown elements with enhancements from https://squidfunk.github.io/mkdocs-material/

+

Cover image

+

Once code works perfectly, look for cover image. It can be .png or .webp. Place image to the tools/include/images/CON004.webp

+ +
Header: tools/include/markdown/CON004-header.md
Portainer simplifies your Docker container management via Portainer web interface. It enables faster deploy of the applications and it gives real time visibility.
+
+ +
Footer: tools/include/markdown/CON004-footer.md
1
+2
+3
+4
+5
=== "Access to the web interface"
+
+    The web interface is accessible via port **9002**:
+
+    - URL = `http://<your.IP>:9002`
+
+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/611/Developer-Guide_Adding-Board-Family/index.html b/611/Developer-Guide_Adding-Board-Family/index.html new file mode 100644 index 000000000..c59dfe8be --- /dev/null +++ b/611/Developer-Guide_Adding-Board-Family/index.html @@ -0,0 +1,1810 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Adding a new board or board family - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+ +
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/611/Developer-Guide_Build-Commands/index.html b/611/Developer-Guide_Build-Commands/index.html new file mode 100644 index 000000000..44e647b69 --- /dev/null +++ b/611/Developer-Guide_Build-Commands/index.html @@ -0,0 +1,1980 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Build Commands - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Build commands

+

kernel

+

Builds kernel and device tree (where applicable) and places it to the output/debs

+

Usage: +

Bash
./compile.sh kernel BOARD=nanopi-r5c BRANCH=edge
+

+

kernel-config

+

Automatically call kernel’s make menuconfig (add or remove modules or features)

+

Usage: +

Bash
./compile.sh kernel-config BOARD=nanopi-r5c BRANCH=edge
+

+

dts-check

+

Validate dts files and improve board & patch development overall.

+

This option validates the dts/dtb file for the selected board against the device tree bindings and outputs the validation logs to the user. It can be used when adding a new board, developing or improving a dts file.

+

Usage: +

Bash
./compile.sh dts-check BOARD=nanopi-r5c BRANCH=edge 
+

+

inventory-boards

+

Outputs a one-board-per-line CSV inventory of boards.

+

Sets TARGETS_FILE to something that doesn’t exist, so the default-targets.yaml is used (so same list for everyone, save for userpatched-boards)

+

Usage: +

Bash
./compile.sh inventory-boards
+
+Outputs /info/boards-inventory.csv

+

kernel-dtb

+

Builds only DTB and outputs full preprocessed dts source

+

Outputs preprocessed DTS source for the board in question to output/ +also outputs the same preprocessed DTS source, ran through dtc with input and output DTS formats for “normalized” comparisons

+

Usage: +

Bash
./compile.sh kernel-dtb BOARD=xxxxx BRANCH=edge
+

+

rewrite-uboot-patches

+

Prepares git, applies patches to git, and rewrites them back from git +same as kernel, it does git archeology for mbox-less patches, etc.

+
    +
  • uboot-patches-to-git alias is also added, but my guess is that the rewrite is more useful.
  • +
  • refactor a common config function for both kernel and uboot.
  • +
+

Usage: +

Bash
./compile.sh rewrite-uboot-patches BOARD=xxxx BRANCH=edge 
+

+

rewrite-kernel-patches

+

Prepares git, applies patches to git, and rewrites them back from git +same as kernel, it does git archeology for mbox-less patches, etc.

+

Usage: +

Bash
./compile.sh rewrite-kernel-patches BOARD=xxxx BRANCH=edge 
+

+

targets

+

Generates output/info/git_sources.json file containing URL, branch, and commit hash combo.

+

The easiest way to generate file for all devices is to run ./compile.sh targets. Then, at the time of release, we will copy the output/info/git_sources.json file to config/sources/git_sources.json. Once the file is copied, the hash information from the file will be used to fetch resources for git repositories where branches are specified instead of tags or commits.

+

Usage: +

Bash
./compile.sh targets
+

+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/611/Developer-Guide_Build-Preparation/index.html b/611/Developer-Guide_Build-Preparation/index.html new file mode 100644 index 000000000..4c5b9575d --- /dev/null +++ b/611/Developer-Guide_Build-Preparation/index.html @@ -0,0 +1,1984 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Getting Started - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Armbian Build Framework Quick Start Guide

+

Requirements

+
    +
  • x86_64 / aarch64 / riscv64 machine
  • +
  • at least 4GB of memory and ~50GB of disk space for VM, container or bare metal installation
  • +
  • Armbian / Ubuntu Jammy 22.04.x for native building or any Docker capable Linux for containerised
  • +
  • Windows 10/11 with WSL2 subsystem running Armbian / Ubuntu Jammy 22.04.x
  • +
  • Superuser rights (configured sudo or root access).
  • +
  • Make sure your system is up-to-date! Outdated Docker binaries, for example, can cause trouble
  • +
+

Clone repository

+
Bash
1
+2
git clone https://github.com/armbian/build
+cd build  
+
+
+

Note

+
    +
  • Make sure that full path to the build script does not contain spaces
  • +
  • For stable branch use last point release --branch=v24.11
  • +
+
gitGraph
+   commit
+   commit
+   checkout main
+   commit id: "v24.08" tag: "v24.08"
+   branch v24.08
+   commit
+   commit
+   commit
+   commit
+   checkout main
+   commit id: "v24.11" tag: "v24.11"
+   branch v24.11
+   commit
+   commit
+   commit
+   commit
+   checkout main
+   commit
+   commit
+   commit
+   commit
+   commit
+   commit
+   commit id: "main" type: REVERSE tag: "Trunk"
+
+

Interactive

+

Run framework:

+
Bash
./compile.sh
+
+
+Video +

+
+

CLI

+

Comprehensive list of build Commands and Switches

+

Example:

+
Bash
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
./compile.sh build \
+BOARD=uefi-x86 \
+BRANCH=current \
+BUILD_DESKTOP=yes \
+BUILD_MINIMAL=no \
+DESKTOP_APPGROUPS_SELECTED='browsers chat desktop_tools' \
+DESKTOP_ENVIRONMENT=gnome \
+DESKTOP_ENVIRONMENT_CONFIG_NAME=config_base \
+KERNEL_CONFIGURE=no \
+RELEASE=noble
+
+
+

Interpretation?

+

This command will generate Ubuntu 24.04 Noble based Gnome desktop environment image for Intel based hardware (uefi-x86). Besides bare desktop, it will contain packages from browsers and desktop_tool sections and it will use unchanged kernel from current kernel branch.

+
+

GitHub actions

+

If you do not own the proper equipment to build images on your own, you can use our GitHub action.

+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/611/Developer-Guide_Build-Switches/index.html b/611/Developer-Guide_Build-Switches/index.html new file mode 100644 index 000000000..852e94c86 --- /dev/null +++ b/611/Developer-Guide_Build-Switches/index.html @@ -0,0 +1,2243 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Build Switches - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Build Switches

+

These parameters are meant to be applied to the ./compile.sh command. They are all optional. They can also be added to your build configuration file to save time. Default values are marked bold if applicable.

+

User space

+

BOARD ( string )

+

Set the name of the board manually to skip the dialog prompt. Name of the board is a filename without extension.

+

BRANCH ( string )

+
    +
  • vendor
  • +
  • legacy
  • +
  • current (recommended)
  • +
  • edge
  • +
+

Set kernel and U-Boot branch manually to skip dialog prompt

+
+

Note

+

Some branches may not be available for all devices.

+
+

RELEASE ( string )

+
    +
  • bookworm
  • +
  • trixie
  • +
  • sid
  • +
  • jammy
  • +
  • noble
  • +
+

Set packages release base manually to skip dialog prompt. Check here for currently available releases.

+
+

Note

+

Only stable and/or LTS upstream Debian or Ubuntu releases are officially supported. Others might work or not.

+
+

BUILD_MINIMAL ( string )

+
    +
  • yes: build a bare CLI image suitable for application deployment. This option is not compatible with BUILD_DESKTOP="yes"
  • +
  • no: (default)
  • +
+

BSPFREEZE ( string )

+
    +
  • yes: freeze (from upgrade) armbian firmware packages when building images (U-Boot, kernel, DTB, BSP)
  • +
  • no: (default)
  • +
+

INSTALL_HEADERS ( string )

+
    +
  • yes: pre-install kernel headers
  • +
  • no: (default)
  • +
+
+ +

Networking

+

NETWORKING_STACK ( string )

+
    +
  • network-manager
  • +
  • systemd-networkd
  • +
  • none (to not-add any networking extensions)
  • +
+

Installs desired networking stack. If the parameter is undefined, it sets systemd-networkd for minimal images (MINIMAL=yes) and network-manager for the rest. Time synchronization is also changed; chrony is installed with network-manager, while systemd-timesyncd is used with systemd-networkd. In both cases, we control network settings using Netplan.

+
+

Build switch example

+
Text Only
./compile.sh NETWORKING_STACK="network-manager"
+
+
+
+ +

Host environment

+

EXPERT

+
    +
  • yes
  • +
+

Show development features and boards regardless of their support status in interactive mode.

+

CLEAN_LEVEL (comma-separated list)

+

Defines what should be cleaned. Changing this option can be useful when rebuilding images or building more than one image

+
    +
  • make-atf = make clean for ATF, if it is built.
  • +
  • make-uboot = make clean for uboot, if it is built.
  • +
  • make-kernel = make clean for the kernel if it is built. very slow.
  • +
  • debs, alldebs = delete all packages in “./output/debs”
  • +
  • images = delete “./output/images”
  • +
  • cache = delete “./output/cache”
  • +
  • sources = delete cache/sources (all downloaded sources)
  • +
  • oldcache = remove old cached rootfs except for the newest 8 files
  • +
  • extras = delete additional packages for the current release in output/debs/extra
  • +
+

CARD_DEVICE ( string )

+
    +
  • /dev/sdX
  • +
+

Set to the device of your flash media / SD card. The image will be burned and verified.

+

PREFER_DOCKER ( string )

+
    +
  • yes (default)
  • +
  • no
  • +
+

Docker assisted compilation is on by default. Set to no if you prefer running compilation natively.

+

DOCKER_ARMBIAN_BASE_IMAGE ( string )

+
    +
  • ubuntu:jammy (default)
  • +
  • ubuntu:noble
  • +
  • debian:bookworm
  • +
+

Defines the build host when using a Docker container (default). Here, you can see which other options are available.

+
    +
  • CI ( string )
      +
    • true
    • +
    • false
    • +
    +
  • +
+

If enabled (true), the Docker build container will receive Docker credentials from the host +(${HOME}/.docker/config.json) and the OCI_TARGET_BASE environment variable.

+
    +
  • OCI_TARGET_BASE ( string )
      +
    • url/to/container_registry/path
    • +
    • ${GHCR_SOURCE}/armbian/* (GHCR_SOURCE is defined in lib/functions/configuration/main-config.sh)
    • +
    +
  • +
+

Select the target for pull/push OCI cached images. If not set, default is used.

+
    +
  • GHCR_MIRROR_ADDRESS (string)
  • +
+

The default mirror address for ghcr.io, set by GHCR_MIRROR=dockerproxy, is ghcr.dockerproxy.com. When this address is unavailable, an alternative address can be set with GHCR_MIRROR_ADDRESS.

+

Example:

+
Text Only
./compile.sh GHCR_MIRROR=dockerproxy GHCR_MIRROR_ADDRESS=ghcr.libcuda.so
+
+
    +
  • KERNEL_COMPILER (string)
  • +
+

The compiler used to compile the kernel. Usually, this option is set by the board config, but it can be set to clang to use LLVM to compile the kernel.

+

Example:

+
Text Only
./compile.sh KERNEL_COMPILER=clang
+
+
    +
  • OPENSSHD_REGENERATE_HOST_KEYS (boolean)
      +
    • false (skip armbian-firstrun’s OpenSSH host keys deletion and regeneration (eg: to let cloud-init set the SSH host keys)
    • +
    • true (execute armbian-firstrun’s OpenSSH host keys deletion + regeneration)
    • +
    +
  • +
+

Manage OpenSSH host key regeneration at armbian-firstrun service.

+

Example:

+
Text Only
./compile.sh OPENSSHD_REGENERATE_HOST_KEYS=false
+
+
+ +

Filesystem

+

ROOTFS_TYPE ( string )

+
    +
  • ext4 (default)
  • +
  • f2fs
  • +
  • btrfs
  • +
  • nilfs2
  • +
  • xfs
  • +
  • nfs
  • +
+

Create image with different root filesystems instead of default ext4. Requires setting FIXED_IMAGE_SIZE to something smaller than the size of your SD card for F2FS

+

BTRFS_COMPRESSION ( string )

+
    +
  • lzo
  • +
  • none
  • +
  • zlib (default)
  • +
  • zstd
  • +
+

When choosing ROOTFS_TYPE=btrfs, select btrfs filesystem compression method and compression level. By default, the compression is zlib.

+
+

Note

+

The script does not check the legality of the input variable (compression ratio). Input like zlib:1234 is legal to the script but illegal to the kernel. Beware that setting this option does affect image creation only (shrinking disk size) and will not adjust /etc/fstab, so it is up to the user to later edit /etc/fstab if compression in daily operation is also wanted (beware of severe performance penalties with random IO patterns and heavy compression algorithms!).

+
+

CRYPTROOT_ENABLE ( string )

+
    +
  • yes
  • +
  • no
  • +
+

LUKS (Linux Unified Key Setup) is a specification for block device encryption. It establishes an on-disk format for the data, as well as a passphrase/key management policy. LUKS uses the kernel device mapper subsystem via the dm-crypt module.

+
When enabled, you need to provide additional information:
1
+2
+3
+4
+5
CRYPTROOT_PASSPHRASE="MYSECRECTPASS"             # Mandatory
+CRYPTROOT_SSH_UNLOCK="yes"                       # Default: yes
+CRYPTROOT_SSH_UNLOCK_PORT="2222"                 # Default: 2022
+CRYPTROOT_MAPPER=armbian-root`                   # Default: armbian-root
+CRYPTROOT_PARAMETERS="custom cryptsetup options" # Default: --pbkdf pbkdf2
+
+
+

Tips and warnings

+
    +
  • Private key can be placed in $USERPATCHES_PATH/dropbear_authorized_keys or they will be generated in output/images/*.key file
  • +
  • If you want to do the encryption part from scratch, check out this forum post.
  • +
  • This function might not work well with all distributions.
  • +
  • CRYPTROOT_MAPPER name might affect parallel image building
  • +
  • CRYPTROOT_PARAMETERS may not contain =; separate switches with spaces
  • +
+
+
+ +

Advanced

+

INCLUDE_HOME_DIR ( string )

+
    +
  • yes
  • +
  • no (default)
  • +
+

Include directories created inside /home in final image.

+

ENABLE_EXTENSIONS ( comma-separated list )

+

Extensions allows to extend the Armbian build system without overloading the core with specific functionality. Extensions, stored in folder extensions are called

+
+

Build switch example

+
Text Only
1
+2
+3
+4
+5
+6
+7
+8
+9
./compile.sh \
+build \
+BOARD=uefi-x86 \
+BRANCH=current \
+BUILD_DESKTOP=no \
+BUILD_MINIMAL=no \
+KERNEL_CONFIGURE=no \
+RELEASE=noble \
+ENABLE_EXTENSIONS=mesa-vpu,nvidia \
+
+
+

CONSOLE_AUTOLOGIN

+
    +
  • yes (default)
  • +
  • no
  • +
+

Automatically login as root for local consoles at first run. Disable if your security threat model requires.

+

USE_CCACHE +- yes +- no (default)

+

Use a C compiler cache. Generally not needed due to git-worktree . Can slow performance on clean builds.

+

PRIVATE_CCACHE +- yes +- no (default)

+

Use $DEST/ccache as ccache home directory. Setting yes to this will enable CCACHE as well.

+

ARTIFACT_IGNORE_CACHE ( string )

+
    +
  • yes
  • +
  • no (default)
  • +
+

Enforce building from source instead of using pre-built artifacts.

+

SKIP_ARMBIAN_REPO ( string )

+
    +
  • yes
  • +
  • no (default)
  • +
+

Enforce building without Armbian repository. Suitable for developing new releases or making custom images that doesn’t need Armbian repository.

+

Build options below need to be retested and added above (COULD BE DEPRECATED)

+

⚠ DO NOT USE! Obsolete documentation, new documentation above is in progress.

+
    +
  • KERNEL_KEEP_CONFIG ( yes | no ):
      +
    • yes: use kernel config file from previous compilation for the same branch, device family, and version
    • +
    • no: use default or user-provided config file
    • +
    +
  • +
  • BUILD_DESKTOP ( yes | no ):
      +
    • yes: build an image with a minimal desktop environment
    • +
    • no: build image with console interface only
    • +
    +
  • +
  • CREATE_PATCHES ( yes | no ) ⚠ Warning: This option is deprecated and may be removed in future releases - use the new kernel-patch / uboot-patch / atf-patch CLI commands instead.
      +
    • yes: prompt right before the compilation starts to make changes to the source code for both U-Boot and kernel. From these changes, patch files will be created and placed in the output directory. If you want these patches included in a normal run (without CREATE_PATCHES to say), these files must be copied to the appropriate directories. Also, see user-provided patches.
    • +
    +
  • +
  • EXT=rkdevflash to flash Rockchip images to eMMC either during image build or separately with flash CLI command (only works bare Linux, not Docker)
  • +
+

Hidden options to minimize user input for build automation

+
    +
  • ARMBIAN_CACHE_ROOTFS_PATH ( string ): bind mount cache/rootfs to defined folder
  • +
  • ARMBIAN_CACHE_TOOLCHAIN_PATH ( string ): bind mount cache/toolchain path to defined folder
  • +
+

Hidden options for advanced users (default values are marked bold)

+
    +
  • USERPATCHES_PATH ( userpatches/ ): set alternate path for the location of the userpatches folder
  • +
  • SKIP_EXTERNAL_TOOLCHAINS ( yes | no ): don’t download and use Linaro toolchains, by default placed in cache/toolchain (and configurable with ARMBIAN_CACHE_TOOLCHAIN_PATH)
  • +
  • PROGRESS_DISPLAY ( none | plain | dialog ): way to display output of verbose processes - compilation, packaging, debootstrap
  • +
  • PROGRESS_LOG_TO_FILE ( yes | no ): duplicate output, affected by the previous option, to log files output/debug/*.log
  • +
  • NO_APT_CACHER ( yes | no ): disable usage of APT cache. Default yes in containers, but can be overridden
  • +
  • DISABLE_IPV6 ( true | false ): The distant future, the year Two-Thousand. Set false to allow Aria2c to use a modern ip protocol.
  • +
  • NO_HOST_RELEASE_CHECK ( yes | no ): overrides the check for a supported host system
  • +
  • USE_MAINLINE_GOOGLE_MIRROR ( yes | no ): use the googlesource.com mirror for downloading mainline kernel sources, which may be faster than git.kernel.org depending on your location
  • +
  • USE_GITHUB_UBOOT_MIRROR ( yes | no ): use an unofficial GitHub mirror for downloading mainline U-Boot sources, may be faster than git.denx.de depending on your location
  • +
  • SYNC_CLOCK ( yes | no ): sync system clock on builder before start image creation process
  • +
  • OFFLINE_WORK ( yes | no ): skip downloading and updating sources and time and host check. Set to “yes,” and you can collect packages without accessing the internet
  • +
  • FORCE_USE_RAMDISK ( yes | no ): overrides autodetect for using tmpfs in new debootstrap and image creation process
  • +
  • FIXED_IMAGE_SIZE ( integer ): create an image file of this size (in megabytes) instead of minimal
  • +
  • BOOTSIZE ( integer 96 ): set size (in megabytes) for separate /boot filesystem. Used if ROOTFS_TYPE set to non-ext4
  • +
  • COMPRESS_OUTPUTIMAGE (comma-separated list): create a compressed archive with an image file and GPG signature for redistribution
      +
    • sha: generate SHA256 hash for image
    • +
    • gpg: sign image using gpg
    • +
    • 7z: compress image, hash, and signature to 7z archive
    • +
    • gz: compress image only using gz format
    • +
    • xz: compress image only using xz format
    • +
    • yes: compatibility shortcut for sha,gpg,7z
    • +
    +
  • +
  • IMAGE_XZ_COMPRESSION_RATIO ( 1 - 9 ) images compression levels when using xz compressor. Beware of memory consumption when going higher
  • +
  • SEVENZIP ( yes | no ): create .7z archive with extreme compression ratio instead of .zip
  • +
  • BUILD_KSRC ( yes | no ): create kernel source packages while building…
  • +
  • INSTALL_KSRC ( yes | no ): … and pre-install these kernel sources on the image
  • +
  • FORCE_BOOTSCRIPT_UPDATE ( yes | no ):
      +
    • yes: force bootscript to get updated during bsp package upgrade
    • +
    +
  • +
  • NAMESERVER ( IPv4 address ): the DNS resolver used inside the build chroot. Does not affect the final image. Default: 1.0.0.1
  • +
  • DOWNLOAD_MIRROR ( china | bfsu ): select download mirror for toolchain and debian/ubuntu packages
      +
    • china: use mirrors.tuna.tsinghua.edu.cn; it will be very fast thanks to Tsinghua University
    • +
    • bfsu: use mirrors.bfsu.edu.cn, the mirror of Beijing Foreign Studies University
    • +
    • leave empty to use official source
    • +
    +
  • +
  • ARMBIAN_MIRROR (auto): override automated mirror selection, example ‘ARMBIAN_MIRROR=”https://yourlocalmirror.com”‘
  • +
  • MAINLINE_MIRROR ( google | tuna | bfsu ): select mainline mirror of linux-stable.git
      +
    • google: use the mirror provided by Google, the same as USE_MAINLINE_GOOGLE_MIRROR=yes
    • +
    • tuna: use the mirror provided by Tsinghua University
    • +
    • bfsu: use the mirror provided by Beijing Foreign Studies University, which is similar to tuna
    • +
    • leave empty to use the official git.kernel.org, which may be very slow for mainland China users
    • +
    +
  • +
  • UBOOT_MIRRORgithub | gitee : select mainline mirror of u-boot.git
      +
    • github: use the mirror provided by github, the same as USE_GITHUB_UBOOT_MIRROR=yes
    • +
    • gitee: use the mirror provided by Gitee, a Chinese git services
    • +
    • leave empty to use the official source.denx.de, which may be very slow for mainland China users
    • +
    +
  • +
  • GITHUB_MIRROR ( fastgit | gitclone | cnpmjs ): select download mirror for GitHub hosted repository
      +
    • fastgit: use the mirror provided by fastgit.org
    • +
    • gitclone: use the mirror provided by gitclone.com
    • +
    • cnpmjs: use the mirror provided by cnpmjs.org
    • +
    • leave empty to connect directly to GitHub, which may be very slow for mainland China users
    • +
    +
  • +
  • REGIONAL_MIRROR ( china ): select mirrors based on regional setting, will not overwrite explicitly specified mirror option
      +
    • china: MAINLINE_MIRROR=tuna, UBOOT_MIRROR=gitee, GITHUB_MIRROR=fastgit, DOWNLOAD_MIRROR=china
    • +
    • leave empty to use default settings
    • +
    +
  • +
  • ROOT_FS_CREATE_ONLY ( yes | no ): set to yes to force local cache creation
  • +
  • EXTRAWIFI ( yes | no ): include several drivers for WiFi adapters
  • +
+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/611/Developer-Guide_Building-with-Docker/index.html b/611/Developer-Guide_Building-with-Docker/index.html new file mode 100644 index 000000000..3964d43fa --- /dev/null +++ b/611/Developer-Guide_Building-with-Docker/index.html @@ -0,0 +1,1953 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Building with Docker - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Building with Docker

+

Officially supported and tested method for building with Docker

+

This method works for building u-boot and kernel packages as well as building full OS images. +Note! +To write fresh-builded image directly to sdcard or other block device you have to enable +Docker run in privileged mode. +Uncomment line DOCKER_FLAGS+=(--privileged) in file userpatches\config-docker.conf or your own docker-config file.

+

Building additional packages (EXTERNAL_NEW) is not supported.

+

Requirements

+
    +
  • x86/x64/aarch64/armhf Linux host that supports running a recent Docker daemon. Refer to Docker documentation for details.
  • +
  • Docker version 17.06 CE or newer.
  • +
  • Enough free disk space on the storage used for Docker containers and named volumes. Named volumes path can be changed using standard Docker utilites, + refer to Docker documentation for details.
  • +
+

Installation (https://docs.docker.com/engine/install/)

+

Details

+

There are 3 options to start build process:

+

1. By passing configuration file name (config-<conf_name>.conf), stored in userpatches directory, as an argument: +

Text Only
./compile.sh docker <conf_name>
+
+2. By passing addtional line arguments to compile.sh after docker: +
Text Only
./compile.sh docker KERNEL_ONLY=yes BOARD=cubietruck BRANCH=current KERNEL_CONFIGURE=yes
+
+3. Interactively run inside docker container +
Text Only
./compile.sh docker-shell BOARD=rockpi-4a BRANCH=edge RELEASE=jammy
+

+

The process creates and runs a named Docker container armbian with two named volumes armbian-cache and armbian-ccache, +and mounts local directories output and userpatches.

+

Options 1 and 2 compile the same as without Docker but in separate environment to prevent changes to the base system.

+

The dockerfile of the created container is placed in userpatches directory, and all container-related options can be changed +in userpatches/config-docker.conf file. Templates of both files are located in the config/templates directory.

+

docker-shell interactive mode

+

The docker-shell interactive mode is useful for when you need to do more than just “make an image.” This mode allows you to edit +U-Boot and kernel sources before and after applying patches, investigate compilation errors, and so on.

+

This mode also allows you to manually run individual steps of the build process.

+

First, start docker-shell on the host build system: +

Text Only
@droid:~/armbian$ ./compile.sh docker-shell RELEASE=bullseye BOARD=rockpi-4a BRANCH=edge
+
+From there, RELEASE=bullseye BOARD=rockpi-4a BRANCH=edge are passed into shell and will be set into +envirounment variables.

+

Next, we can simply start building an image: +

Text Only
root@75ec76203b65:~/armbian# ./compile.sh
+
+Alternatively, you can run any function defined in the compile.sh script.

+

For example, to compile U-Boot, prepare the environment with: +

Text Only
./compile.sh default prepare_host compile_sunxi_tools install_rkbin_tools
+
+Then, build U-Boot: +
Text Only
./compile.sh default compile_uboot
+
+To compile only the source code as it is without patching or modifications, run: +
Text Only
./compile.sh default COMPILE_ONLY=yes compile_uboot
+
+Note that you must enter docker-shell after a docker build, as you must +download all of the required toolchains and sourcecodes beforehand.

+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/611/Developer-Guide_Building-with-Multipass/index.html b/611/Developer-Guide_Building-with-Multipass/index.html new file mode 100644 index 000000000..5f6b229e1 --- /dev/null +++ b/611/Developer-Guide_Building-with-Multipass/index.html @@ -0,0 +1,1925 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Building with Multipass - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Building with Multipass

+

In order to build an Armbian image from scratch, whether for development purposes or to apply user customizations on top of a base image, a build environment is required. Per the Armbian documentation, Ubuntu 22.04 is the officially supported build platform.

+

Multipass that is designed for quick and painless provisioning of Ubuntu VMs.

+

Creating a VM and preparing for build

+

Multipass is available for macOS, Windows and Linux platforms.

+

Once you have multipass installed, a Jammy (22.04) instance with 4 CPUs, 4GB of RAM and 25GB of space available can be provisioned with a single command:

+
Bash
multipass launch --cpus 4 --disk 25G --mem 4G --name jammy
+
+

Clone the build repo

+

You can run commands direct on the instance to clone the build repo:

+
Bash
multipass exec jammy -- bash -c "git clone --depth 1 https://github.com/armbian/build" 
+
+

Use an instance

+

Then you can get a shell to the instance and run the build as needed:

+
Bash
1
+2
+3
+4
+5
+6
C:\> multipass shell armbian
+Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.4.0-48-generic x86_64)
+Last login: Tue Jan 30 12:23:08 2024 from 172.22.111.1
+# Let's get building!  
+ubuntu@armbian:~$ cd build
+ubuntu@armbian:~/build$ ./compile.sh BOARD=orangepizero ... etc
+
+

Share data with an instance

+

The recommended way to share data between your host and an instance with Multipass is the command:mount +

Bash
1
+2
multipass mount /my/dir jammy
+multipass info jammy
+

+

Mounts: /my/dir => /my/dir

+

From this point on will be available inside the instance./my/dir

+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/611/Developer-Guide_Extensions-Hooks/index.html b/611/Developer-Guide_Extensions-Hooks/index.html new file mode 100644 index 000000000..f3cc81490 --- /dev/null +++ b/611/Developer-Guide_Extensions-Hooks/index.html @@ -0,0 +1,2308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Extensions Hooks - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Extension Hooks

+
    +
  • This file is autogenerated by the armbian/build repository.
  • +
+

Hooks

+
    +
  • Hooks are listed in the order they are called.
  • +
+

post_family_config

+
+

give the config a chance to override the family/arch defaults

+
+

This hook is called after the family configuration (sources/families/xxx.conf) is sourced. Since the family can +override values from the user configuration and the board configuration, it is often used to in turn override those.

+

Also known as (for backwards compatibility only):

+
    +
  • config_tweaks_post_family_config
  • +
+

user_config

+
+

Invoke function with user override

+
+

Allows for overriding configuration values set anywhere else. It is called after sourcing the lib.config file if it +exists, but before assembling any package lists.

+

extension_prepare_config

+
+

allow extensions to prepare their own config, after user config is done

+
+

Implementors should preserve variable values pre-set, but can default values an/or validate them. This runs after +user_config. Don’t change anything not coming from other variables or meant to be configured by the user.

+

post_aggregate_packages

+
+

For final user override, using a function, after all aggregations are done

+
+

Called after aggregating all package lists, before the end of compilation.sh. Packages will still be installed after +this is called, so it is the last chance to confirm or change any packages.

+

Also known as (for backwards compatibility only):

+
    +
  • user_config_post_aggregate_packages
  • +
+

post_determine_cthreads

+
+

give config a chance modify CTHREADS programatically. A build server may work better with hyperthreads-1 for example.

+
+

Called early, before any compilation work starts.

+

Also known as (for backwards compatibility only):

+
    +
  • config_post_determine_cthreads
  • +
+

add_host_dependencies

+
+

run before installing host dependencies

+
+

you can add packages to install, space separated, to ${EXTRA_BUILD_DEPS} here.

+

fetch_sources_tools

+
+

fetch host-side sources needed for tools and build

+
+

Run early to fetch_from_repo or otherwise obtain sources for needed tools.

+

build_host_tools

+
+

build needed tools for the build, host-side

+
+

After sources are fetched, build host-side tools needed for the build.

+

pre_install_distribution_specific

+
+

give config a chance to act before install_distribution_specific

+
+

Called after create_rootfs_cache (prepare basic rootfs: unpack cache or create from scratch) but +before install_distribution_specific (install distribution and board specific applications).

+

Also known as (for backwards compatibility only):

+
    +
  • config_pre_install_distribution_specific
  • +
+

pre_install_kernel_debs

+
+

called before installing the Armbian-built kernel deb packages

+
+

It is not too late to unset KERNELSOURCE here and avoid kernel install.

+

post_install_kernel_debs

+
+

allow config to do more with the installed kernel/headers

+
+

Called after packages, u-boot, kernel and headers installed in the chroot, but before the BSP is installed. +If KERNELSOURCE is (still?) unset after this, Armbian-built firmware will not be installed.

+

post_family_tweaks

+
+

customize the tweaks made by $LINUXFAMILY-specific family_tweaks

+
+

It is run after packages are installed in the rootfs, but before enabling additional services. It allows implementors +access to the rootfs (${SDCARD}) in its pristine state after packages are installed.

+

pre_customize_image

+
+

run before customize-image.sh

+
+

This hook is called before customize-image.sh is executed and before the overlay is mounted. It thus can be used +for the same purposes as customize-image.sh without the overlay.

+

Also known as (for backwards compatibility only):

+
    +
  • image_tweaks_pre_customize
  • +
+

post_customize_image

+
+

post customize-image.sh hook

+
+

Run after the customize-image.sh script is run, and the overlay is unmounted.

+

Also known as (for backwards compatibility only):

+
    +
  • image_tweaks_post_customize
  • +
+

post_post_debootstrap_tweaks

+
+

run after removing diversions and qemu with chroot unmounted

+
+

Last chance to touch the ${SDCARD} filesystem before it is copied to the final media. It is too late to run any +chrooted commands, since the supporting filesystems are already unmounted.

+

Also known as (for backwards compatibility only):

+
    +
  • config_post_debootstrap_tweaks
  • +
+

pre_prepare_partitions

+
+

allow custom options for mkfs

+
+

Good time to change stuff like mkfs opts, types etc.

+

Also known as (for backwards compatibility only):

+
    +
  • prepare_partitions_custom
  • +
+

prepare_image_size

+
+

allow dynamically determining the size based on the $rootfs_size

+
+

Called after ${rootfs_size} is known, but before ${FIXED_IMAGE_SIZE} is taken into account. A good spot to +determine FIXED_IMAGE_SIZE based on rootfs_size. UEFISIZE can be set to 0 for no UEFI partition, or to a size in MiB +to include one. Last chance to set USE_HOOK_FOR_PARTITION=yes and then implement create_partition_table hook_point.

+

Also known as (for backwards compatibility only):

+
    +
  • config_prepare_image_size
  • +
+

post_create_partitions

+
+

called after all partitions are created, but not yet formatted

+
+

format_partitions

+
+

if you created your own partitions, this would be a good time to format them

+
+

The loop device is mounted, so ${LOOP}p1 is it’s first partition etc.

+

pre_update_initramfs

+
+

allow config to hack into the initramfs create process

+
+

Called after rsync has synced both /root and /root on the target, but before calling update_initramfs.

+

Also known as (for backwards compatibility only):

+
    +
  • config_pre_update_initramfs
  • +
+

pre_umount_final_image

+
+

allow config to hack into the image before the unmount

+
+

Called before unmounting both /root and /boot.

+

Also known as (for backwards compatibility only):

+
    +
  • config_pre_umount_final_image
  • +
+

post_umount_final_image

+
+

allow config to hack into the image after the unmount

+
+

Called after unmounting both /root and /boot.

+

Also known as (for backwards compatibility only):

+
    +
  • config_post_umount_final_image
  • +
+

post_build_image

+
+

custom post build hook

+
+

Called after the final .img file is built, before it is (possibly) written to an SD writer.

+
    +
  • NOTE: this hook used to take an argument ($1) for the final image produced. + - Now it is passed as an environment variable ${FINAL_IMAGE_FILE} + It is the last possible chance to modify $CARD_DEVICE.
  • +
+

run_after_build

+
+

hook for function to run after build, i.e. to change owner of $SRC

+
+

Really one of the last hooks ever called. The build has ended. Congratulations.

+
    +
  • NOTE: this will run only if there were no errors during build process.
  • +
+

extension_metadata_ready

+
+

meta-Meta time!

+
+

Implement this hook to work with/on the meta-data made available by the extension manager. Interesting stuff to process:

+
    +
  • "${EXTENSION_MANAGER_TMP_DIR}/hook_point_calls.txt" contains a list of all hook points called, in order.
  • +
  • For each hook_point in the list, more files will have metadata about that hook point. + - ${EXTENSION_MANAGER_TMP_DIR}/hook_point.orig.md contains the hook documentation at the call site (inline docs), + hopefully in Markdown format. + - ${EXTENSION_MANAGER_TMP_DIR}/hook_point.compat contains the compatibility names for the hooks. + - ${EXTENSION_MANAGER_TMP_DIR}/hook_point.exports contains exported environment variables. + - ${EXTENSION_MANAGER_TMP_DIR}/hook_point.vars contains all environment variables.
  • +
  • ${defined_hook_point_functions} is a map of all the defined hook point functions and their extension information.
  • +
  • ${hook_point_function_trace_sources} is a map of all the hook point functions that were really called during the + build and their BASH_SOURCE information.
  • +
  • ${hook_point_function_trace_lines} is the same, but BASH_LINENO info. After this hook is done, + the ${EXTENSION_MANAGER_TMP_DIR} will be removed.
  • +
+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/611/Developer-Guide_Extensions/index.html b/611/Developer-Guide_Extensions/index.html new file mode 100644 index 000000000..6b7ab221f --- /dev/null +++ b/611/Developer-Guide_Extensions/index.html @@ -0,0 +1,2030 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Extensions - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Extensions

+
+

“I’m gonna create a prepare_bootloader hook [in core] so we can refactor u-boot [into an extension]”

+
+

The extensions framework allows the board/family developers, extension authors, and users to extend the Armbian build system without overloading the core with specific functionality.

+

It’s a simple framework, written in Bash, that works based on function naming conventions. It provides the core and the extensions with tracing and debugging, (error control,?) inline documentation and very simple dependency resolution.

+

Terminology

+
    +
  • The “core” is everything that’s in lib/ directory plus compile.sh and some others. It’s the spine of the build system.
  • +
  • An “extension” is a separate Bash source file that contains exclusively functions. Extensions live in extensions/ or userpatches/extensions/ directory, but could one day be in a separate repository too.
  • +
  • An “extension method” (a.k.a “hook”) is used by the core to call extensions, via call_extension_method(). This will discover all enabled extension methods implementations, order them, and call them one by one. + - The Armbian core already has quite a few of these in strategic spots. + - More are coming as they’re identified.
  • +
  • An “extension method implementation” is a function that will be called when it’s extension method is called. It can be defined in extensions, but also in board config, family config, user config, etc.
  • +
+

Example

+
Core calls extensions
+

The Armbian core build system has an extension method called run_after_build, also known as the “run_after_build hook”. You can find it in lib/main.sh around line 546.

+
Bash
1
+2
# in lib/main.sh:546
+call_extension_method "run_after_build" [...]
+
+
Extension method implementation
+

Consider the following function:

+
Bash
1
+2
+3
function run_after_build__say_congratulations() { 
+  echo "Congrats, the build is finished!"
+}
+
+

Such a function is an “extension method implementation” called say_congratulations for the extension method run_after_build.

+
Extension file
+

A file userpatches/extensions/be-festive.sh containing the above function is an “extension” called be-festive.

+
Using it
+

An user of the build system can enable that extension by adding a call to enable_extension "be-festive" on his configuration file, or by passing ENABLE_EXTENSIONS=be-festive as a parameter to the build.

+

Naming conventions and ordering

+

An extension method implementation is just a Bash function that follows the pattern run_after_build__say_congratulations where

+
    +
  • run_after_build is the name of the extension method.
  • +
  • __ is a marker/separator – very important – two underscores, not one, not three.
  • +
  • say_congratulations is the name of the extension method implementation, and should be unique.
  • +
+

The system will “magically” compose a single run_after_build() function, based on all the hook functions that begin with run_after_build__.

+

Hook functions will be sorted by their numerical value; hook functions that do not begin with a number will receive 500_ prefix automatically.

+

So the examples run_after_build__do_this and run_after_build__500_do_this are equivalent, and will run

+
    +
  • sooner than run_after_build__900_do_smth_else
  • +
  • later than run_after_build__300_do_even_another_thing
  • +
+

What is an extension?

+

A extension is Bash source file that contains exclusively:

+
    +
  • function definitions: + - extension method implementation definitions (with __ separator) + - other internal functions (for structure and clarity if needed)
  • +
  • calls to enable_extension "another-extension" at the top of the file. + - that’s a very simple dependency system, one extension can enable another.
  • +
+

Specifically, extension files should not contain any code outside of functions – they should do nothing when sourced.

+

Extensions can be official Armbian fragments and live in /extensions, or can be user-specific +in /userpatches/extensions.

+

An extension could be implemented in any of the following file/dir structures:

+
    +
  • /extensions/our-ext.sh - an official, single-file extension.
  • +
  • /userpatches/extensions/my-ext.sh - a user-specific, single-file extension.
  • +
  • /extensions/our-dir-ext/our-dir-ext.sh - an official, directory-based extension.
  • +
  • /userpatches/extensions/my-dir-ext/my-dir-ext.sh - a user-specific, directory-based extensions.
  • +
+

The official extensions can be used by boards, family includes, etc, while the user-specific extensions can only be used by userpatches code or via ENABLE_EXTENSIONS=my-ext,my-dir-ext build parameter.

+

Single-file vs Directory-based

+

They’re the same, except:

+
    +
  • Directory-based extensions will be passed a ${EXTENSION_DIR} environment variable.
  • +
  • That is useful if there are other files/assets that belong together with that extension. An example would be a template file, some configuration file, or other static asset that is directly related to the extension.
  • +
  • Using directory-based extensions and ${EXTENSION_DIR} allows for easy moving and PR’ing of user extensions.
  • +
+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/611/Developer-Guide_Overview/index.html b/611/Developer-Guide_Overview/index.html new file mode 100644 index 000000000..c91ddef5f --- /dev/null +++ b/611/Developer-Guide_Overview/index.html @@ -0,0 +1,1964 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Overview - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Overview

+ +

What it does?

+
    +
  • Builds custom kernel, image or a Debian based Linux distribution optimized for low-resource hardware,
  • +
  • Include filesystem generation, low-level control software, kernel image and bootloader compilation,
  • +
  • Provides a consistent user experience by keeping system standards across different platforms.
  • +
+
graph LR
+  A[./compile.sh] --> B{Change<br>kernel<br>config};
+  B ---> |yes| C["HW"];
+  B ---> |no| C["HW"];
+  C ---> |branch| D["legacy<br>vendor<br>current<br>edge"];
+  D --> |base| E["Debian<br>Ubuntu"];
+  E ---> |type| F["CLI"];
+  F ---> |type| G["Server"];
+  F ---> |type| H["Minimal"];
+  E ---> I["Desktop"];
+  I ---> K["XFCE"];
+  I ---> L["Gnome"];
+  I ---> M["Cinammon"];
+  I ---> N["KDE Neon"];
+

Key Advantages

+
    +
  • Simplicity with interactive graphical interface.
  • +
  • Generates widely recognized and well maintained userspace
  • +
  • Fast learning curve for complex operations
  • +
+

Check other similarities, advantages and disadvantages compared with leading industry standard build software.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionArmbianYoctoBuildroot
Targetgeneral purposeembeddedembedded / IOT
U-boot and kernelcompiled from sourcescompiled from sourcescompiled from sources
Board support maintenance  completeoutsideoutside
Root file systemDebian or Ubuntu basedcustomcustom
Package managerAPTanynone
Configurabilitylimitedlargelarge
Initramfs supportyesyesyes
Getting startedquickvery slowslow
Cross compilationyesyesyes
+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/611/Developer-Guide_User-Configurations/index.html b/611/Developer-Guide_User-Configurations/index.html new file mode 100644 index 000000000..58f5fae48 --- /dev/null +++ b/611/Developer-Guide_User-Configurations/index.html @@ -0,0 +1,1947 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + User Configurations - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

User Configuration

+

User provided patches

+

You can add your own patches outside build script. Place your patches inside appropriate directory, for kernel or u-boot. There are no limitations except all patches must have file name extension .patch. User patches directory structure mirrors directory structure of patch. Look for the hint at the beginning of patching process to select proper directory for patches. Example:

+
Text Only
1
+2
[ o.k. ] Started patching process for [ kernel sunxi-edge 4.4.0-rc6 ]
+[ o.k. ] Looking for user patches in [ userpatches/kernel/sunxi-edge ]
+
+

Patch with same file name in userpatches directory tree substitutes one in patch. To replace a patch provided by Armbian maintainers, copy it from patch to corresponding directory in userpatches and edit it to your needs. To disable a patch, create empty file in corresponding directory in userpatches.

+

User provided configuration

+

If file userpatches/lib.config exists, it will be called and can override the particular kernel and u-boot versions. It can also add additional packages to be installed, by adding to PACKAGE_LIST_ADDITIONAL. For a comprehensive list of available variables, look through lib/configuration.sh. Some examples of what you can change:

+
Text Only
1
+2
+3
PACKAGE_LIST_ADDITIONAL="$PACKAGE_LIST_ADDITIONAL python-serial python" # additional packages
+[[ $LINUXFAMILY == sunxi64 && $BRANCH == edge ]] && BOOTBRANCH='tag:v2017.09' # conditionally change u-boot git branch/tag
+KERNELBRANCH="tag:v5.4.28" #always change to this kernel tag
+
+

User provided kernel config

+

If file userpatches/linux-$LINUXFAMILY-$BRANCH.config exists, it will be used instead of default one from config. Look for the hint at the beginning of kernel compilation process to select proper config file name. Example:

+
Text Only
1
+2
[ o.k. ] Compiling current kernel [ 5.10.47 ]
+[ o.k. ] Using kernel config provided by user [ userpatches/linux-rockchip64-current.config ]
+
+

User provided sources config overrides

+

If file userpatches/sources/$LINUXFAMILY.conf exists, it will be used in addition to the default one from config/sources. Look for the hint at the beginning of compilation process to select proper config file name. +Please note that there are some exceptions for LINUXFAMILY like sunxi (32-bit mainline sunxi) and sunxi64 (64-bit mainline sunxi)

+

Example:

+
Text Only
1
[ o.k. ] Adding user provided sunxi64 overrides
+
+

User provided image customization script

+

You can run additional commands to customize created image. Edit file:

+
Text Only
1
userpatches/customize-image.sh
+
+

and place your code here. You may test values of variables noted in the file to use different commands for different configurations. Those commands will be executed in a chroot environment just before closing image.

+

To add files to image easily, put them in userpatches/overlay and access them in /tmp/overlay from customize-image.sh

+

Be advised that even though you are compiling an image on an amd64 machine, any additional apt packages you configure or commands you run in customize-image.sh will be automatically installed/executed/virtualized for the architecture of the build target SBC.

+

Partitioning of the SD card

+

In case you define $FIXED_IMAGE_SIZE at build time the partition containing the rootfs will be made of this size. Default behaviour when this is not defined is to shrink the partition to minimum size at build time and expand it to the card’s maximum capacity at boot time (leaving an unpartitioned spare area of ~5% when the size is 4GB or less to help the SD card’s controller with wear leveling and garbage collection on old/slow cards).

+

You can prevent the partition expansion from within customize-image.sh by a touch /root/.no_rootfs_resize or configure the resize operation by either a percentage or a sector count using /root/.rootfs_resize (50% will use only half of the card’s size if the image size doesn’t exceed this or 3887103s for example will use sector 3887103 as partition end. Values without either % or s will be ignored)

+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/611/Developer-Guide_Welcome/index.html b/611/Developer-Guide_Welcome/index.html new file mode 100644 index 000000000..5fcff013a --- /dev/null +++ b/611/Developer-Guide_Welcome/index.html @@ -0,0 +1,1888 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Welcome to the Armbian build framework documentation! - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Welcome to the Armbian build framework documentation!

+

Overview:

+

(ANSI) Logging

+

Log output is stored in output/logs and provided in a few different formats. ANSI coloring is applied to both the screen and the log files themselves.
+Please add SHARE_LOG=yes to automatically upload logs to our paste service and provide us with the given url when reporting issues.
+That will allows us to check the logs on a web browser and keep to correct formatting.

+

Command line syntax has changed

+

General CLI syntax: ./compile.sh PARAM=value OTHER_PARAM=other_value [<configfile> <configfile> ...] [<command>]

+
    +
  • where command defaults to build if not specified; could also be kernel-config or u-boot etc…
  • +
  • config file names must not have the same name as a possible <command> (system will check & bomb if so)
  • +
  • also: there is no more default config – you have to be explicit
  • +
  • also: there is no more docker config – Docker is fully auto-managed now. The system will complain if you have one.
  • +
  • parameters like PARAM=value, <configfile> or <command> can be applied in any order.
  • +
+

No more config-default.conf, config file name needs to be specified in the command line

+
    +
  • No “default” config is auto-loaded anymore. Default config lead to unreproducible failing builds and was a source of + confusion.
  • +
  • The configs still go to the same place, userpatches/config-xyz.conf – but the name has to be provided to the build system to, + like ./compile.sh BOARD=xxx xyz; otherwise works the same.
  • +
+

Artifacts, cache, what the …?

+

The armbian/build system is currently undergoing refactoring to improve its structure. Previously, the build system +was a single, very complex bash script that mixed the building of .deb packages with the creation of images.

+

This was reworked into a 1-to-N image-to-artifact dependency tree; a certain image build will depend on N possible +“artifacts”. Artifacts are either .deb packages, a .tar of multiple .deb packages, or a rootfs.tar.zstd. Each +artifact can be individually built, and has a specific name and a version.

+

Each artifact is also now cached by default using OCI storage at ghcr.io (GitHub Container Registry). To achieve +consistent caching, each artifact produces a version that includes hashes of its composing files, variables, +patches, hooks, external git SHA1 references, etc. That way we can consistently check the remote OCI cache for previously-built +artifacts, and possibly save image builders from having to build heavy packages just to produce an image.

+

TL;DR about artifacts and caching:

+
    +
  • KERNEL_ONLY=yes and KERNEL_ONLY=no are deprecated. Use the kernel CLI command instead.
  • +
  • ARTIFACT_IGNORE_CACHE=yes can help with false positives. Please also report the problem, with a complete logfile.
  • +
+

Automatic Docker/sudo launcher

+
    +
  • compile.sh will prefer to use Docker if it detects Docker is installed and working. + - This handles Docker Desktop and Rancher Desktop (in Docker emulation mode) under macOS/Darwin, including Apple + M1/M2. + - You don’t need and actually can’t have the old docker config file.
  • +
  • If Docker is not installed, it will try to use sudo to run the build as root.
  • +
  • If you run directly as root, it will give a warning and asks to run without sudo.
  • +
+

Kernel Git Trees: shallow vs full

+

During the build, depending on which local or remote caches are hit, it might be necessary to build the Linux Kernel from scratch.

+

The kernel’s git repo is huge. Most build systems resort to fetching “shallow” trees directly from upstream git servers, +to save bandwidth. Unfortunately that creates immense extra CPU load on the git servers. To avoid this problem, +Armbian produces daily automated git tree exports cached in ghcr.io OCI repositories, and only uses git fetch to +update the relatively small new changes from the upstream git server.

+

There are two types of cached Kernel git trees:

+
    +
  • full is a complete git tree, including all of Torvald’s master and all of the currently-supported stable + branches. + - full is very large download and requires a lot of disk space. + - full is more useful over time and when building multiple different kernels on the same machine, like for CI + servers or developer workstations.
  • +
  • shallow is a shallow tree for a specific stable branch + - shallow is a much smaller download and requires less disk space + - shallow is appropriate for restricted devices like SBCs which will build a single kernel
  • +
+

**TL;DR: ** KERNEL_GIT=full or KERNEL_GIT=shallow or let the system decide for you.

+

Consider forking before cloning the repo

+

Before cloning the repo, consider forking it first. This will allow you to make changes and submit pull requests. +You will need a GitHub account to do this; +see GitHub’s documentation for more +information. +If you fork, make sure to keep your fork up-to-date with the main repo, by rebasing your fork.

+

Some really confusing stuff still remains

+

This is (by far) not a complete list:

+
    +
  • wifi/other kernel drivers are still using pre-armbian-next code, and are very hard to work with. it is not only the + contents are a mess, the way the whole thing works leads to more and more compounding work. To make it worse, family + patches sometimes need to patch driver code, leading to a cycle of sadness for developers. We are still coming up with + a plan to completely replace this lest most of us go insane.
  • +
  • although “aggregation” has been rewritten in Python, it still mostly works using the legacy principle, by scanning + directories and files in a very complex and error-prone way. This is a source of many bugs and confusion. We plan to + replace this with pure extensions eventually.
  • +
  • we have mostly working kernel headers (linux-headers pkg) for 5.10+ including some vendor kernels
  • +
+

Multiple u-boot’s for same board

+

We can build u-boot twice, using UBOOT_TARGET_MAP. Some example I did in https://github.com/armbian/build/blob/main/config/boards/odroidhc4.conf#L15-L20 may help.

+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/611/Development-Code_Review_Procedures_and_Guidelines/index.html b/611/Development-Code_Review_Procedures_and_Guidelines/index.html new file mode 100644 index 000000000..fcdae4109 --- /dev/null +++ b/611/Development-Code_Review_Procedures_and_Guidelines/index.html @@ -0,0 +1,1858 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Development Code Review Procedures and Guidelines - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Development Code Review Procedures and Guidelines

+ +

Development Code Review Procedures and Guidelines

+ This topic should give you as a developer a brief overview about what you should do, must do, aswell as can and can not do. What you as devepoler can expect from Armbian and what we expect from you. +

+

Requirements:

+ Even though you may already be a developer, just to make sure, here is an outline of the expectations for this process: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ReviewApproveMerge
Github ID:white_check_mark::x::x:
Armbian Github Organisation Collaborator:white_check_mark::white_check_mark::x:
Armbian Github Organisation Member:white_check_mark::white_check_mark::white_check_mark:

Armbian Organization Members are required to have:

You should know development basics like how to get an Armbian image running on your hardware, do basic debugging, building a kernel and how to use the Armbian build system.

+

Code Review:

+ Some helpful guidelines for pull requests and code reviews +

+ It has often been said that programming is part art, part science - that is because lots of times there is no single, simple solution to a problem. Or if there is, we might not know about it. There is also an infamous joke that if there are n developers in the room, then there are n+1 opinions on how things should be done. That being said, here are some guidelines that should prevent friction when submitting or reviewing code. +

The most important thing

The code has to work.

Unless you open a PR (“pull request”) as a work in progress, the code should be built and tested on a device or emulator. Do not rely on CI test automation!

If you have touched the build files and changed build setup, it is useful to test the whole build from scratch (clean build) and all of the types and flavours. If you updated external libraries, test the pertaining features. If you changed the build version, make a build and test that the version is correct.

Having people review your code is one thing, but you should not expect them to also test the code for you when not explicitly asked for.

Context

One important thing that lots of guidelines forget to mention is the context of the pull request: Sometimes it is a big refactor, sometimes it is a new feature, sometimes it is a bugfix. Some of those might be more urgent than others, and sometimes you might be under pressure to ship ASAP so the code might not be perfect or there will not be any tests or code might not be extendable. That is ok.

Everyone

  • There is no perfect code: good enough is usually good enough. That being said, try to keep the number of WTFs per minute to a minimum.
  • Accept that many programming decisions are opinions. Discuss trade-offs, which you prefer, and reach a resolution quickly.
  • Ask for clarification. ("I didn't understand. Can you clarify?")
  • Offer clarification, explain the decisions you made to reach a solution in question. + Avoid using terms that could be seen as referring to personal traits. ("dumb", "stupid"). Assume everyone is intelligent and well-meaning.
  • Be humble. ("I'm not sure - let's look it up.")
  • Do not use hyperbole ("always", "never", "endlessly", "nothing"). Avoid sarcasm.
  • Remember that you are both on the same side - the goal is to make the code better. Understand that sometimes your ideas will be overruled. Even if you do turn out to be right, do not take revenge or say, "I told you so".
  • Talk synchronously (e.g. chat, screensharing, in person) if there are too many "I didn't understand" or "Alternative solution:" comments. Pull requests should not be the place for long discussions, architectural or otherwise.
  • Put notes on what is missing or could be improved in the PR description or comments. You can also make a Jira ticket with discussions points and possible problems or things to do and discuss it offline.
  • As a Code Submitter

  • PRs should be about one thing. If you do multiple things in one PR, it is hard to review. If you are fixing stuff as you go, you might want to make atomic commits and then cherry-pick those commits into separate branches, leaving the PR clean.
  • Try to keep the PRs small.
  • Having a PR description is useful. Additionally, you can also link to the Jira ticket.
  • Ideally, the PR should be finished when submitted. If the PR is work in progress, add (WIP) or [WIP] to the title.
  • You should have tests that at least cover the logic, and ideally also cover the input/output parameters and methods. (depends on context)
  • Make sure to add a documentation PR when needed https://github.com/armbian/documentation
  • As a Reviewer

  • Reviewing code is part of a normal workday. You should check for open/updated PRs / Jira ticket as often as you can.
  • Ask, do not tell. (“What do you think about trying…?” rather than “Don’t do…”)
  • Offer ways to simplify or improve code.
  • Code beautification and refactoring ought to be tasks in the next sprint, except for obvious and easy-to-fix things.
  • Communicate which ideas you feel strongly about and those you do not. Explain your reasons why code should be changed. (Not in line with the style guide? A personal preference?)
  • If you disagree strongly, consider giving it a few minutes before responding; think before you react.
  • Offer alternative implementations, but assume the author already considered them. ("What do you think about using a custom validator here?")
  • If discussions turn too theoretical or touch big architectural questions, move the discussion offline. In the meantime, let the author make the final decision on alternative implementations.
  • Do not keep the code hostage. Keep in mind the context and the most important thing - does it work?
  • Merging a merge request

    Before making the decision to merge:

  • Set a milestone.
  • Consider warnings and errors from Github CI bots, code quality bots, and other reports. Unless a strong case can be made for the violation, these should be resolved before merging. A comment must be posted if the PR is merged with any failed job.
  • If the PR contains both quality and non-quality-related changes, the PR should be merged by the relevant maintainer or senior software engineer after the quality related changes are approved by more then one software engineer.

  • If a pull request is fundamentally ready, but needs only trivial fixes (such as typos), consider demonstrating a bias for action by making those changes directly without going back to the author. You can do this by using the suggest changes feature to apply your own suggestions to the pull request.

    Note that:

  • merging is limited to Armbian Github Organization members, you can apply here to become one, if you have not already been invited.
  • If the changes are not straightforward, please prefer allowing the author to make the change.
  • Before applying suggestions, edit the pull request to make sure squash and merge is enabled

  • Authors are not authorized to merge their own pull requests and need to seek approval from another maintainer / developer to merge.

    Armbian's Assistance

    If you have questions about being a developer or want to learn more and deeper insights about the build framework, Armbian will try to guide you to the appropriate documentation or information in a best-effort fashion. If time allows, at our descrection, we will try our best to explain and teach you personally various aspects about our processes. If best effort guidance is not enough, contact us for professional assistance.

    If you have any concerns please do not hesitate to reach out via forums, IRC or Discord. Armbian cares about the people who care about Armbian  :)

    References / Sources:

    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/Mirrors/index.html b/611/Mirrors/index.html new file mode 100644 index 000000000..ae586ca0e --- /dev/null +++ b/611/Mirrors/index.html @@ -0,0 +1,2406 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Mirrors - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Mirrors

    + +

    Space needs:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    MirrorCommandSize
    Current imagesrsync -av rsync://rsync.armbian.com/dl540G
    Packagesrsync -av rsync://rsync.armbian.com/apt177G
    Old imagesrsync -av rsync://rsync.armbian.com/archive1.8T
    Very old imagesrsync -av rsync://rsync.armbian.com/oldarchive5.4T
    +
      +
    1. Chose target and setup HTTP/HTTPS hostname
    2. +
    3. Setup cron to sync every 2-4 hours
    4. +
    5. Inform us
    6. +
    +

    Current Mirrors

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    SiteTime ZoneFlagSpeedPackagesImagesArchiveRsync
    Atomo NetworksEurope/RomeItaly2500 Mbps✅✅✅✅
    Auroradev ChicagoAmerica/ChicagoEast coast1000 Mbps✅✅
    Auroradev Las VegasAmerica/Los_AngelesWest coast10000 Mbps✅✅✅✅
    NardolEurope/ParisFrance1000 Mbps✅✅✅
    SystemonachipEurope/ViennaAustria1000 Mbps✅✅✅
    TNA HostingAmerica/New_YorkNorth America1000 Mbps✅✅✅
    Naho.moe AustraliaAustralia/SydneyAustralia10000 Mbps❌❌
    SBC mirror AustraliaAustralia/SydneyAustralia1000 Mbps✅✅
    Naho.moe GermanyEurope/BerlinGermany1000 Mbps❌❌
    SBC mirror SpainEurope/MadridSpain1000 Mbps✅✅
    Fast MirrorEurope/KievUkraine1000 Mbps✅✅
    Hetzner GermanyEurope/BerlinGermany1000 Mbps✅✅✅✅
    ImolaEurope/LjubljanaSlovenia1000 Mbps✅✅✅
    Naho.noe IndiaAsia/KolkataIndia1000 Mbps✅✅
    Naho.moe JapanAsia/TokyoJapan10000 Mbps❌❌
    Naho.moe KoreaAsia/SeoulKorea1000 Mbps❌❌
    Kspace EstoniaEurope/TallinnEstonia10000 Mbps✅✅✅✅
    AlbonyAsia/KolkataDynamic1000 Mbps✅
    SteeManAmerica/ChicagoVirginia1000 Mbps❌
    Airframes EuropeEurope/BerlinGermany1000 Mbps❌❌
    HostikoEurope/KievUkraine20000 Mbps✅✅
    ISCASAsia/ShanghaiChina10000 Mbps✅✅
    OSS PlanetAsia/TaipeiTaiwan1000 Mbps✅
    Alibaba MirrorsAsia/ShanghaiChina10000 Mbps✅✅
    BFSUAsia/ShanghaiChina10000 Mbps✅✅
    dotsrc.orgEurope/CopenhagenDenmark20000 Mbps✅✅
    Jevin Canders LLCAmerica/New_YorkEast coast10000 Mbps✅✅
    SJTUAsia/ShanghaiChina10000 Mbps✅
    Nanjing UniversityAsia/ShanghaiChina10000 Mbps✅✅
    Shanghai Tech UniversityAsia/ShanghaiChina10000 Mbps✅✅
    SUSTechAsia/ShanghaiChina10000 Mbps✅
    Tsinghua UniversityAsia/ShanghaiChina10000 Mbps✅✅
    USTCAsia/ShanghaiChina10000 Mbps✅✅
    xTomEurope/BerlinGermany10000 Mbps✅
    Digital Streaming Co.Asia/TaipeiTaiwan50000 Mbps✅✅
    Airframes PhoenixAmerica/PhoenixWest coast1000 Mbps❌❌
    Airframes SeattleAmerica/Los_AngelesWest coast1000 Mbps❌❌
    Airframes SeattleAmerica/Los_AngelesWest coast1000 Mbps❌❌
    Airframes St LouisAmerica/ChicagoEast coast1000 Mbps✅✅
    VineHost.NETEurope/LondonUnited Kingdom1000 Mbps✅✅
    YandexEurope/MoscowRussia10000 Mbps✅✅
    Netcup GermanyEurope/BerlinGermany2500 Mbps✅
    Jing RocksAsia/TokyoJapan10000 Mbps✅✅
    Naho.moe SingaporeAsia/SingaporeSingapore1000 Mbps❌❌
    SBC mirror SingaporeAsia/SingaporeSingapore1000 Mbps✅✅
    JetHomeEurope/MoscowRussia2000 Mbps✅✅✅
    Naho.moe UKEurope/LondonUnited Kingdom1000 Mbps❌❌
    Naho.noe USA westAmerica/New_YorkNorth America1000 Mbps❌❌
    XogiumEurope/ParisFrance500 Mbps✅✅✅
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/Process_Armbian-Task-Tracking/index.html b/611/Process_Armbian-Task-Tracking/index.html new file mode 100644 index 000000000..76790c79d --- /dev/null +++ b/611/Process_Armbian-Task-Tracking/index.html @@ -0,0 +1,1857 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Armbian Task Management - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Armbian Task Management

    +

    Overview

    +

    TLDR; Keep task discussions in the forum. GitHub Issues are just for task metadata.

    +

    Tasks associated with code will have an issue created in GitHub, but all dialog regarding tasks will reside on the forum in a topic containing the github Issue ID of the task.

    +

    What is a task?

    +

    A task is something actionable that results in some sort of tangible output. ex: code, documentation, QA findings.

    +

    Example sources of tasks include: feature requests, bugs, QA, general following of development roadmap.

    +

    Not all support issues are tasks, but a support issue can generate a task.

    +

    Task Creation Procedure

    +
      +
    1. Create issue in Armbian GitHub Repo under appropriate milestone + - step1
    2. +
    3. Copy the numeric ID of issue created
    4. +
    5. Create new topic under the Tasks subforum on the Armbian Forums + - Use the the naming convention of [ISSUE_ID] - Issue Name + - step2
    6. +
    7. Copy the URL of task subforum topic just created
    8. +
    9. +

      Create comment on GitHub Issue with the following Content:

      +
      Text Only
      1
      +2
      +3
        Please keep all discussion for this issue on the forum topic available below:
      +
      +  [URL](URL)
      +
      +

      - step4

      +
    10. +
    11. +

      Lock comments on GitHub Issue

      +
    12. +
    +

    Task tracking with GitHub Issues

    +

    GitHub Issues provide an easy method to track and filter tasks by using tags and milestones. Issues also make it easy to easily associate commits and merge requests with a task. Effectively we just use GitHub issues for the metadata for reporting.

    +

    Labels

    +

    Use labels identify the purpose of a task.

    +
      +
    • bug is used to tag tasks that address Armbian-level bugs
    • +
    • not-our-bug is used to identify tasks that are bugs in upstream code. They are not Armbian bugs, but may impact Armbian.
    • +
    • enhancement is used to identify tasks that are new features for Armbian.
    • +
    +

    Milestones

    +

    Use milestones to divide tasks into claimed and unclaimed work.

    +
      +
    • claimed tasks milestone contains tasks which have been assigned.
    • +
    • unclaimed tasks milestone contains tasks that need an owner.
    • +
    +

    Forum Tasks

    +

    Converting a topic to a task

    +

    Sometimes support discussions can become tasks. A forum admin can assist in moving the topic to Tasks forum group. A cooresponding issue will need to be created.

    +

    Future Process Improvements

    +

    Enhancements desired for this process (This should be a task!)

    +

    Issue Hook

    +

    Ideally we can have a forum topic created upon issue creation. This will save some time.

    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/Process_CI/index.html b/611/Process_CI/index.html new file mode 100644 index 000000000..2b995063d --- /dev/null +++ b/611/Process_CI/index.html @@ -0,0 +1,2346 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Automation - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Automation for developers and maintainers

    +

    Core automation for generating images for release are held at armbian/os

    +

    Prepare build lists

    + +

    Recommended images on download pages are defined via regular expression mapping file exposed.map:

    +

    Example:

    +
    Text Only
    1
    +2
    bananapim7/archive/Armbian_[0-9].*Bananapim7_noble_vendor_[0-9]*.[0-9]*.[0-9]*_gnome-kisak_desktop.img.xz
    +bananapim7/archive/Armbian_[0-9].*Bananapim7_bookworm_vendor_[0-9]*.[0-9]*.[0-9]*_minimal.img.xz
    +
    +

    Standard support images

    +

    Build templates

    +

    They have definitions on what kind of images we want to build - for section or for one specific board:

    +
    YAML
    1
    +2
    +3
    +4
    userpatches/targets-release-apps.template
    +userpatches/targets-release-community-maintained.template
    +userpatches/targets-release-nightly.template
    +userpatches/targets-release-standard-support.template
    +
    +

    From those templates we are autogenerating YAML files, which are passed to build matrix as input. Make sure to review generated YAML files if they have wanted build targets with correct exensions enabled.

    +

    Blacklisting

    +

    Autogeneration is excluded for boards that are on blacklists:

    +
    YAML
    1
    +2
    userpatches/targets-automation.blacklist
    +userpatches/targets-automation-nightly.blacklist
    +
    +

    We do this if we are not happy with the automation outcomes and want to define build targets in the template.

    +

    Extensions

    +

    Each board variant can have additional extensions and they are defined in this file:

    +
    Text Only
    userpatches/targets-extensions.map
    +
    +

    Example:

    +
    Text Only
    khadas-edge2,legacy:vendor:,ENABLE_EXTENSIONS="image-output-oowow,v4l2loopback-dkms,mesa-vpu"
    +
    +

    Prepare Standard Support images for release

    +
    +Info +

    Manual executing permissions are tied to release manager role.

    +
    +

    Build Standard Support Images

    +

    This build workflow is executed manually when making:

    +
      +
    • a set of images for specific device
    • +
    • a set of images for specific maintainer
    • +
    • a full set of stable release images (default)
    • +
    +

    Notes:

    +
      +
    • this process prepares images for release without pushing them to the download pages
    • +
    • you can only generate images that are defined in targets-release-standard-support.yaml build lists!
    • +
    • images generation workflows are compiled and are pretty much the same, just with different defaults
    • +
    +

    1. Open workflow and click

    +

    Run Workflow

    +

    2. Select board

    +

    Workflow

    +

    Bump version: Select if you want to trigger system wide version bump. +Version override: Set version under which you want to release images.

    +

    Images versions are stored in JSON files: +- https://github.com/armbian/os/blob/main/stable.json +- https://github.com/armbian/os/blob/main/nightly.json

    +

    3. Run workflow

    +

    Build

    +

    (Workflow takes around 15 minutes to complete. In case of network issues it can also take hours)

    +

    Generated images are uploaded to incoming folder https://rsync.armbian.com/incoming/ under your GitHub username and once they are confirmed working, please notify @igorpecovnik to move them to official download pages. Once images are moved to main download section, automation refreshes download pages index within 15-30 minutes.

    +

    Aditional options

    +

    Generates stable images defined in targets-release-standard-support.yaml.

    +

    We are generating several images for each download / hardware target. They are automatically sorted by sections:

    +
      +
    • Desktop releases
    • +
    • Server and IOT releases
    • +
    • Dedicated applications
    • +
    +

    Images generation can be customized:

    +
      +
    • Framework build branch
        +
      • main (make images from trunk)
      • +
      • vXX.X (previous stable release)
      • +
      +
    • +
    • Bump Version (system wide version bump)
    • +
    • Version override (in case you don’t want to use latest)
    • +
    • Board (make images for one board only)
    • +
    • Maintainer (make images for selected maintainer)
    • +
    +

    Prepare application images for release (release manager)

    +

    Build Dedicated Application Images

    +

    This build workflow is executed manually when making:

    +
      +
    • a set of application images for specific device
    • +
    • a set of application images for specific maintainer
    • +
    • a full set of application images (default)
    • +
    +

    Notes:

    +
      +
    • application images are released 10-15 minutes after build finishes succesfully
    • +
    • you can only generate images for applications that are defined in targets-release-apps.yaml build lists!
    • +
    • images generation workflows are compiled and are pretty much the same, just with different defaults
    • +
    +

    1. Open workflow and click

    +

    Run Workflow

    +

    2. Select board

    +

    Workflow

    +

    Version override: Use this feature if you want to keep them under the same version, but not lower then last released.

    +

    3. Run workflow

    +

    Build

    +

    (Workflow takes around 15 minutes to complete. In case of network issues it can also take hours)

    +

    Generated images are hosted at GitHub https://github.com/armbian/distribution/releases and released at once. Automation refreshes download pages within 15-30 minutes after/if workflow finished succesfully.

    +

    Dedicated Application Images

    +

    Aditional options

    +

    Generates dedicated application images defined in targets-release-apps.yaml. This file is autogenerated from targets-release-apps.template. (You always edit template)

    +

    Images generation can be customized:

    +
      +
    • framework build branch
        +
      • main (make images from trunk)
      • +
      • vXX.X (previous stable release)
      • +
      +
    • +
    • Bump Version (system wide version bump)
    • +
    • Version override (in case you don’t want to use latest)
    • +
    • board (make images only for one board)
    • +
    • maintainer (make images for selected maintainer)
    • +
    +

    Repository update (cronjob/release manager)

    +

    This pulls packages from build framework OCI cache located at GitHub and from various 3rd party repositories such as Chrome, Chromium, Code, Discord, (latest) ZFS, Thunderbird, Zoom, … and pushes them to:

    +
      +
    • apt.armbian.com (only new packages are added)
    • +
    • beta.armbian.com (whole repository is recreated from scratch)
    • +
    +

    1. Open workflow and click

    +

    Run Workflow

    +

    Action is executed automatically when artifact generations completes. Or manually.

    +

    2. Include artifacts from generated image(s)

    +

    When +- [ ] Add https://netcup.armbian.com/partial/ to stable repo

    +

    is selected.

    +

    3. Run workflow

    +

    Build

    +

    (Workflow takes around 60 minutes to complete)

    +

    Build all artifacts (cronjob)

    +

    Build All Artifacts

    +

    Generates all build artifacts cache for targets defined in targets-all-not-eos.yaml. This build job runs every 8 hours and can also be run manually when needed.

    +

    This build job needs to be successfully completed in order to proceed generating any OS images!

    +

    Build Rolling Release Images (cronjob)

    +

    Build Nightly Images

    +

    Generates all nighly (Rolling Release) images defined in targets-release-nightly.yaml. This file is autogenerated from targets-release-nightly.template.

    +

    This build job runs every day at 9 a.m. UTC and can also be run manually when needed. Download pages are refreshed automatically after successful build.

    +

    Build

    +

    Watchdog (cronjob)

    +

    Runs every 15 minutes and re-trigger failed builds six (6) times before finally gives out. This addresses various instabilities when building many artifacts on different hardware:

    +
      +
    • network timeouts
    • +
    • artifact download failure
    • +
    • loop devices allocation failure
    • +
    • runner running low on space
    • +
    +

    Smoke tests on hardware devices (release manager)

    +

    Smoke testing is preliminary testing to reveal simple failures severe enough to, for example, reject a prospective software release. Our test case is constructed of three steps:

    +

    Smoke

    +
      +
    • powering test equipment, consistent from several network switches, power supplies and dozens of hardware platforms
    • +
    • running upgrade, reboot, repository switch, reboot, … tests in parallel
    • +
    • uploading a test report as build artifact following by powering the devices off.
    • +
    +

    Automatic Pull Requests Labeler (PR)

    +

    Automatic Labeler

    +

    Automatically label new pull request based on the paths of files which are being changed. Configuration file can be found in:

    +
    Text Only
    1
        .github/labeler.yml
    +
    +

    Full distro test builds (cronjob/release manager)

    +

    Build Nightly Images

    +

    Generates all supported build combinations (minimal, cli, desktops) for x86 architecture to check package level changes inconsistency and dependencies.

    +

    Options:

    +
      +
    • Framework build branch
        +
      • main
      • +
      • testing_branch (string)
      • +
      +
    • +
    +

    Build all artifacts (admin/PR)

    +

    Generates artifacts at Pull Requests code. Build starts when label of Pull Request is set to “Build”. Requires administration privileges.

    +

    Lint on shell scripts (PR)

    +

    Lint On Shell Scripts

    +

    Lint

    +

    Run ShellCheck on changed shell scripts and report problems within. Linting runs automatically on pull requests.

    +

    Update tools in build scripts (cronjob/admin)

    +

    Update Tools in Scripts

    +

    Some of our scripts download tools from a repo. These cannot be bumped by Dependabot, so this workflow is a self-created Dependabot to bump versions of those tools to stay up-to-date. This workflow only creates a PR if the version was actually updated. To add a new tool, it just needs to be added to the matrix in the script by filling out all the variables.

    +

    Scorecards security scan (PR)

    +

    Scorecards Security Scan

    +

    Scorecards is an automated tool that assesses a number of important heuristics (“checks”) associated with software security and assigns each check a score of 0-10. You can use these scores to understand specific areas to improve in order to strengthen the security posture of your project. You can also assess the risks that dependencies introduce, and make informed decisions about accepting these risks, evaluating alternative solutions, or working with the maintainers to make improvements.

    +

    Kernel hardening analysis (PR)

    +

    Kernel Hardening Analysis

    +

    This analysis checks kernel configs and run if changed. There are plenty of security hardening options for the Linux kernel. A lot of them are not enabled by the major distros. We have to enable these options ourselves to make our systems more secure.

    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/Process_Contribute/index.html b/611/Process_Contribute/index.html new file mode 100644 index 000000000..b9108e4fc --- /dev/null +++ b/611/Process_Contribute/index.html @@ -0,0 +1,1979 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Contribute - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Collaborate on the project

    +

    Overview

    +
      +
    1. Fork the project.
    2. +
    3. Make one or more well commented and clean commits to the repository.
    4. +
    5. Perform a pull request in Github’s web interface.
    6. +
    +

    If it is a new feature request, do not start the coding first. Remember to open an issue to discuss the new feature. If you want to add code to someone else pull request. Also check collection of git tips which will make your life easier.

    +

    If you are struggling, check WEB or CLI step-by-step guide on contributing.

    +

    Source code

    + +

    Adding a new board?

    +

    There are no detailed instructions on how to add a new board or even a whole new board family to the build script yet. However there are a few commits / pull requests that give clues how to achieve that like

    + +

    Board maintainer

    +

    If you are interested in being a maintainer please review Board Support Rules. Then apply here and wait for acceptance. Once accepted you will be added to our infrastructure. For this reason we need additional information to complete your registration process.

    +
    +

    Requirements?

    +
      +
    • You must have access to the hardware you applied to maintain
    • +
    • You must have a Github ID which should be listed in the documentation
    • +
    • You must have a forums account
    • +
    • You must have an Jira account and keep track of issues filed for your board
    • +
    • You must make sure Armbian management has been informed of all of the above IDs for our documentation
    • +
    • You should know Armbian basics like how to get an Armbian image run on your hardware and do basic debugging, ideally via serial console
    • +
    • Knowledge in development, writing code and so on is optional but welcome
    • +
    +
    +

    Expectations

    +

    Maintainers must not necessarily be persons with development experience. They act as a intersection between end-users and the development team and serve the developers in best-effort manner. They are encouraged to answer basic/simple user questions (if possible, also best effort) without having to bother the development team. They are allowed to record bugs but are not allowed to escalate bugs. Team leaders do.

    +

    Take note that it is still up to development team’s discretion what gets attention since Armbian has to plan carefully how to spend its very limited resources.

    +
      +
    • You must participate in release process. Ideally you attend meetings related to releases. On that occasion you are given the chance to point out critical issues with your board.
    • +
    • You must sign-off that device has been tested, is stable, and ready for release during release process. This basically means you test images that are getting prepared for release https://rsync.armbian.com/incoming/
    • +
    +
    +

    What are we looking for?

    +
      +
    • does the board boot to both CLI and Desktop?
    • +
    • is the desktop usable?
    • +
    • does USB work? (at all or partially)
    • +
    • other things such as wireless, audio
    • +
    +
    +

    If something does not work, this is fine and normal. The important part is that it is documented and we get notified about the issues. Known problems should be placed into the Jira ticket and link placed to the board download page. While not required, you should have a build environment setup so you can build images with the most recent images and test them right away. Your feedback, either positive or negative, is very welcome. You are free to add comments to every commit and pull request.

    +

    Ideally you have multiple microSD cards laying around to test regular updates on current releases and nightly without having to re-flash the same card every time to switch between branches.

    +

    Alternatively you can use auto-built images - they are placed at the ever end of each board download pages under “Rolling releases”.

    +
      +
    • You must provide “best effort” support in the forum. Do not let that wording intimidate you. This is not a complicated task. Regarding forums this can include things like answering obvious questions (for example by pointing to our documentation, ideally directly to the solution page), let the questioner know that additional information is needed for further debugging (e.g. request “armbianmonitor -u” output) or for upgrade issues, ask if they can recreate the issue with a fresh untouched image from: https://www.armbian.com/download/
    • +
    +
      +
    • You must provide “best effort” support in Jira. Review submitted issues for you board made by Armbian’s contributors
    • +
    +

    Release manager

    +

    This role has additional permission that allows preparation of images for release.

    +

    Release managers: +https://github.com/orgs/armbian/teams/release-manager

    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/Process_Managing_Workflow/index.html b/611/Process_Managing_Workflow/index.html new file mode 100644 index 000000000..9685d64fe --- /dev/null +++ b/611/Process_Managing_Workflow/index.html @@ -0,0 +1,1843 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Jira - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Jira

    +

    Jira where development work is entered and prioritized. https://armbian.atlassian.net/

    +

    Issue Types

    +

    When creating issues, try to assign issue type most appropriate. Issue type can be changed later so don’t worry too much. If possible assign to a “Fix Version” aka Release.

    +
      +
    • Epic - useful as placeholders for large requirements. Common objective, overall goals, contains several stories.
    • +
    • Story - Smallest units of functionality that can be achieved in one or two weeks. Non-technical language.
    • +
    • Task - Work that is clearly defined usually by people that will do the work. Specific, technical language.
    • +
    +

    Theme vs Epic vs User Story vs Task

    +

    Special Issue Type

    +
      +
    • Bug - malfunction of the system, an error, flaw, or a default in the system, that causes an incorrect result.
    • +
    +

    Work Queue

    +

    The easiest way to follow the work queue Upcoming Release Kanban Board. This board lists only work select for the upcoming release.

    +

    kanban screenshot

    +

    Use the filter buttons at top to quickly see unassigned work, work assigned to you, bugs, and work recently updated.

    +

    Work is listed in 3 columns, and sorted by priority.

    +

    Columns: +* Todo + * Work prioritized to be done next + * Pick up any task from this column +* In Progress + * Work In Progress +* Done + * Shows recently completed work. Has time limit to keep board clean

    +

    Managing Work

    +

    All issues for an upcoming release are assigned a “Fix Version” to indicate release number.

    +

    Backlog

    +

    With the Kanban Board, there are 2 states for the Upcoming Release backlog.

    +
      +
    • Todo - These tasks are visible the Todo column of the Kanban board. To keep things simple, there shouldnt be more than 5-10 issues in Todo
    • +
    • Backlog – Other tasks seleceted for release, but not are not visible on the Kanban board. The purpose of this is to keep the Todo column clean and easy to work from. As the Todo column clears, prioritize next tasks in backlog by moving them to todo.
    • +
    +

    All issues for an upcoming release are assigned a “Fix Version” to indicate release number.

    +

    Mobile access

    +

    You can download the app for Android or iOS. +Jira mobile

    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/Process_Release-Model/index.html b/611/Process_Release-Model/index.html new file mode 100644 index 000000000..2c4961e44 --- /dev/null +++ b/611/Process_Release-Model/index.html @@ -0,0 +1,2291 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Release Model - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Release Model

    + +

    Rolling releases

    +

    Armbian provides automated daily rolling releases of small selection of images for all supported targets. Images are available at respective board download pages: https://www.armbian.com/download. Armbian also populates its own packages repository so updates are available as an upgrade for existing installations.

    +

    Point releases

    +

    Armbian runs “train” based point releases. Whatever is ready to board the train, does so. Whatever is not has to wait for the next train. This enables us to have a predictable release cycles making it easy to plan. It also puts the responsibility on developers to make sure they have features ready on time.

    +

    Armbian releases quarterly at the end of February, May, August, November. Offset is because we all know that nothing happens for half of December. At the beginning of a release cycle, we have a planning meeting and two weeks before the end of the release we freeze integration of new features.

    +

    Release Cycle

    +

    Releases last three months. Each release starts with a meeting for planning. After planning, developers and development teams build their deliverable using whatever methods (scrum, kanban, waterfall, … ) they want but shall commit their code frequently, leading up to the last 2 weeks. The project does not accept “dumps” of code at the end. Commit early and often on master. Two weeks before the release date, we halt feature integration and only allow bug fixes. At some point during those two weeks, we start the release candidate process. This process starts by pulling a branch off master that will become the release branch. That frees up master for development on the next release. On the release candidate branch we work on bug fixes, and choose “release candidate”, RC, tags. The software at that tag is a candidate for release, and it is submitted to automated and manual tests on real hardware. If automated tests are passing, we can officially tag it as the release. If it does not, we enter another bug fix cycle and create a new release candidate. We iterate until we have a candidate that can be the formal release. Usually, this takes 2-3 cycles and 1-3 weeks of time.

    +

    Development epics, stories and bugs for each release are tracked through Jira.

    +

    Release Branching, Versioning and Tags

    +

    Branches in Armbian follow this convention:

    +
      +
    • Main branch (main): Main development will happen on the main branch. This is the latest and greatest branch, but is always “stable” and “deployable”. All tests always pass on this branch.
    • +
    • Release branch (v24.08 for example): This is a branch per release with frozen external sources.
    • +
    +

    Each Armbian release will have the following version format:

    +

    Format: <major>.<minor>.<revision>

    +

    <major> and <minor> version are incremented at the end of the release cycles while <revision> is incremented for a fix.

    +

    Release Naming

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    versioncodenamerelease monthwork
    19.11VaquitaNovemberdone
    20.02ChiruFebruarydone
    20.05KaguMaydone
    20.08CapleAugustdone
    20.11TamanduaNovemberdone
    21.02UrubuFebruarydone
    21.05JerboaMaydone
    21.08CaracalAugustdone
    21.11SambarNovembercancelled
    22.02PigFebruarydone
    22.05JadeMaydone
    22.08YapokAugustdone
    22.11GoralNovemberdone
    23.02QuollFebruarydone
    23.05SuniMaydone
    23.08ColobusAugustdone
    23.11TopiNovemberdone
    24.02KereruFebruarydone
    24.05HavierMaydone
    24.08YeltAugustdone
    24.11StirkNovemberplanned
    25.02IiwiFebruaryplanned
    25.05CaimanMayplanned
    25.08DunnartAugustplanned
    25.11BrachNovemberplanned
    26.02GoaFebruaryplanned
    +

    by https://www.codenamegenerator.com from unusual animals

    + + +

    Release Coordinating

    +

    Summary

    +

    A release starts as a RC branch cut from main at freeze time. Once a RC branch is cut, main can be unfrozen and development can continue. RC branch is a rolling release that accepts bug fixes. The bug fixes should be cherry-picked back to main branch. Once the RC is stable, a final release as a branch named after its version. A release is never merged to main. Once a release is complete, it only should be updated for severe bugs and security vulnerabilities. A release is only maintained until the next release.

    +

    1. Forum Communication

    +
      +
    • Create a new thread in the Armbian Project Administration forum
        +
      • Ex topic name: Armbian 24.02 (Kereru) Release Thread
      • +
      +
    • +
    • Tag the post with relase, release version, and codename
    • +
    • Use the following template to begin the body of the release thread:
    • +
    +

    Text Only
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    Release Candidate Code Freeze Date: YYYY-MM-DD
    +Release Date: YYYY-MM-DD
    +Release Candidate Branch Link: URL
    +Release Changelog: URL
    +Release Coordinator: @yourname
    +Testing Tracking Sheet: https://example.com/link  (google sheets)
    +
    +The goal of this thread is to discuss testing, bugfixes, and the overall quality of the release.  Once the release is complete, this thread should be locked and unpinned. 
    +
    +- Before Code Freeze – Make note in the thread the incomplete Jira issues tagged for the release example +- After test images are procuded, engage in community for assistants wih testing.. forums, Twitter, etc. share this tool

    +

    2. Release Candidate Branch Management

    +
      +
    • For code freeze – create a RC branch as version-rc ex: v20.02.0-rc
    • +
    • If possible, create Jira tickets for major changes in github that were not tracked in Jira
    • +
    • Begin testing process. See Release Testing
    • +
    • Do not modify branch directy. Only accept PRs
    • +
    • Only accept PRs for bug fixes. No features
    • +
    • Update main branch version to the NEXT release version with -trunk ex. If RC is v20.02.0-rc main becomes v20.05.0-trunk
    • +
    • CI testing should pass on PR
    • +
    • Test images should automatically be built via Igor’s script
    • +
    • Repeat build, test, and bugfix process until release is stable
    • +
    • Cherry-pick bug fixes back into master
    • +
    • Create Final release branch from RC
    • +
    +

    3. Release

    +
      +
    • In Github create a release from final release branch +Enable source freezing for this branch +
      Text Only
      1
      +2
      ./compile.sh targets
      +cp output/info/git_sources.json config/sources/
      +
      +following by commiting this code to build framework.
    • +
    • Copy release notes generated by Jira release into Github form
    • +
    • Add other appropriate information into release Github release notes
    • +
    • Point Armbian build system to new release
    • +
    • Update Armbian documentation to reflect current release
    • +
    • Celebrate
    • +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/Quick_facts/index.html b/611/Quick_facts/index.html new file mode 100644 index 000000000..9d6474bcb --- /dev/null +++ b/611/Quick_facts/index.html @@ -0,0 +1,1831 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Quick Facts - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Quick Facts

    +

    What is Armbian Linux?

    +

    Armbian Linux provides optimized Debian and Ubuntu Linux images for ARM-based SBCs. There is an incredible ecosystem of small computing platforms that are powerful alternatives to the Raspberry Pi. Armbian’s mission is to provide a uniform system offering that is trustworthy to run on any of the dozens of OS-neglected ARM single board computers.

    +

    Challenges

    +

    Armbian is the opposite of Raspbian

    +

    Raspbian has dozens of contributors to focus on a single SBC platform. Armbian has a dozen contributors to focus on 100+ SBCs spread over 30 platforms.

    +

    Balancing Development and Support

    +

    Given the point above, resources are thin. Armbian developers have to focus on the core mission of maintaining the Armbian Build Platform. We heavily rely on other members of the community to support each other. Although Armbian does provide a lot of user friendly features, the reality is that Armbian is for more advanced users. If you are really struggling with your SBC, you may want to consider first getting more comfortable with Raspbian Linux on the Raspberry Pi.

    +

    More SBCs continuously coming to market

    +

    SBC and TV Box manufacturers love to design and ship new products. Unfortunately they do not like to spend time on software and instead rely on community projects such as Armbian to fill in the gaps.

    +

    Benefits

    +

    Simple

    +

    BASH or ZSH shell, standard Debian/Ubuntu utilities. Common and specific features can be with minimalistic menu-driven utility. Login is possible via serial, HDMI/VGA or SSH.

    +

    Light

    +

    No bloatware or spyware. Special utilities are completely optional. Suitable for newcomers and professionals.

    +

    Optimized

    +

    A distributed image is compacted to real data size and starts at around of 1G. Size is optimized for SD card usage. Bigger is better. Installing applications later severely reduces the life of your SD card. They were not designed for this type of usage.

    +

    Fast

    +

    Boards are optimized on kernel and userspace level. DVFS optimization, memory log caching, browser profile memory caching, swap usage tuning, garbage commit delay. Our system runs almost read-only and is one of the the fastest Linux for many development boards in just about every case.

    +

    Secure

    +

    Security level is on a stock Debian/Ubuntu level and can be hardened with the configuration utility. It provides a good starting point for industrial or home usage. The system is regularly inspected by professionals within the community. Each official stable build is thoroughly tested. Images are a direct base for all 3rd party builders.

    +

    Supported

    +

    Providing long term updates, security fixes, documentation, user support.

    +

    Smart

    +

    Deep understanding how boards work, how operating system work and how hardware should be designed to run better. Involved in board design. Experience in Linux since early 90’. Specialized in ARM development boards since 2013.

    +

    Open

    +

    Open source build script and kernel development, maintenance and distribution for more than 30 different ARM and ARM64 Linux kernels. Powerful build and software development tools. Can run in fully parallel mode. Can run under Docker.

    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/Release_Board-Maintainers/index.html b/611/Release_Board-Maintainers/index.html new file mode 100644 index 000000000..2d08e11e1 --- /dev/null +++ b/611/Release_Board-Maintainers/index.html @@ -0,0 +1,1844 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Board Maintainers - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Board Maintainers

    +

    How to become a maintainer?

    +

    If you are interested in being a maintainer please review Board Support Rules. Then apply here and wait for acceptance. Once accepted you will be added to our infrastruture. For this reason we need additional information to complete your registration process.

    +
    +

    Requirements?

    +
      +
    • You must have access to the hardware you applied to maintain
    • +
    • You must have a Github ID which should be listed in the documentation
    • +
    • You must have a forums account
    • +
    • You must have an Jira account and keep track of issues filed for your board
    • +
    • You must make sure Armbian management has been informed of all of the above IDs for our documentation
    • +
    • You should know Armbian basics like how to get an Armbian image run on your hardware and do basic debugging, ideally via serial console
    • +
    • Knowledge in development, writing code and so on is optional but welcome
    • +
    +
    +

    Expectations

    +

    Maintainers must not necessarily be persons with development experience. They act as a intersection between end-users and the development team and serve the developers in best-effort manner. They are encouraged to answer basic/simple user questions (if possible, also best effort) without having to bother the development team. They are allowed to record bugs but are not allowed to escalate bugs. Team leaders do.

    +

    Take note that it is still up to development team’s discretion what gets attention since Armbian has to plan carefully how to spend its very limited resources.

    +
      +
    • You must participate in release process. Ideally you attend meetings related to releases. On that occasion you are given the chance to point out critical issues with your board.
    • +
    • You must sign-off that device has been tested, is stable, and ready for release during release process. This basically means you test images that are getting prepared for release https://rsync.armbian.com/incoming/
    • +
    +
    +

    What are we looking for?

    +
      +
    • does the board boot to both CLI and Desktop?
    • +
    • is the desktop usable?
    • +
    • does USB work? (at all or partially)
    • +
    • other things such as wireless, audio
    • +
    +
    +

    If something does not work, this is fine and normal. The important part is that it is documented and we get notified about the issues. Known problems should be placed into the Jira ticket and link placed to the board download page. While not required, you should have a build environment setup so you can build images with the most recent images and test them right away. Your feedback, either positive or negative, is very welcome. You are free to add comments to every commit and pull request.

    +

    Ideally you have multiple microSD cards laying around to test regular updates on current releases and nightly without having to re-flash the same card every time to switch between branches.

    +

    Alternatively you can use auto-built images - they are placed at the ever end of each board download pages under “Rolling releases”.

    +
      +
    • You must provide “best effort” support in the forum. Do not let that wording intimidate you. This is not a complicated task. Regarding forums this can include things like answering obvious questions (for example by pointing to our documentation, ideally directly to the solution page), let the questioner know that additional information is needed for further debugging (e.g. request “armbianmonitor -u” output) or for upgrade issues, ask if they can recreate the issue with a fresh untouched image from: https://www.armbian.com/download/
    • +
    +
      +
    • You must provide “best effort” support in Jira. Review submitted issues for you board made by Armbian’s contributors
    • +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/Release_Changelog/index.html b/611/Release_Changelog/index.html new file mode 100644 index 000000000..5d6ed66ab --- /dev/null +++ b/611/Release_Changelog/index.html @@ -0,0 +1,8005 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Changelog - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Changelog

    +
      +
    • Note: If a new sub-version is released this does not necessarily mean all boards receive a new version number since most of the time these fixes are targeting a specific board or board family only.
    • +
    +

    What’s Changed

    +

    v24.11.1 (2024-11-28)

    + +

    v24.8.4 (2024-10-12)

    +
      +
    • Recreated images for Radxa Rock 5C, Nanopi M6
    • +
    +

    v24.8.3 (2024-09-13)

    +
      +
    • Recreated images for Radxa Rock 5 ITX, Rockpi E, Odroid M1, Nanopi R6S
    • +
    +

    v24.8.1 (2024-08-31)

    + +

    v24.5.5 (2024-25-7)

    +
      +
    • Recreated Bananapi M7, Khadas Edge 2, Orangepi 5, Orangepi 5 Plus
    • +
    • Sent rk35xx-vendor (6.1.75) and rk35xx-edge (6.10.y) kernel to the stable repository
    • +
    +

    v24.5.4 (2024-21-7)

    +
      +
    • Recreated Radxa ROCK5 ITX images
    • +
    • Recreated Olimex Teres images since they were broken
    • +
    • Sent sunxi64-current kernel to the stable repository
    • +
    • Sent rk35xx-vendor kernel to the stable repository
    • +
    +

    v24.5.3 (2024-01-7)

    +
      +
    • Recreated Helios64 since board was moved under supported
    • +
    • Sent rockchip64-current kernel to the stable repository
    • +
    +

    v24.5.2 (2024-18-6)

    +
      +
    • Recreated Khadas Edge 2 images due to lack of 3D / video acceleration support in 6.1.y
    • +
    • Recreated Orangepi 5 plus images due to missing support for 32GB variant
    • +
    • Recreated Odroid M1 images with new minimal images and KDE Neon desktop
    • +
    • Added Orangepi 5 Pro images
    • +
    +

    v24.5.1 (2024-25-5)

    +

    Closed projects

    +
      +
    • AR-1759 Improve Khadas support
    • +
    • AR-1988 Resolve Rockchip patch maintenance nightmare
    • +
    • AR-2087 Add functionality to freeze git resources
    • +
    • AR-2095 Improve support for Radxa Rock S 0 and test USB and Ethernet
    • +
    • AR-2100 Add KDE Neon desktop to Armbian Jammy
    • +
    • AR-2144 Add support for the Orange Pi 5 Pro
    • +
    • AR-2145 Add mainline Panthor driver to 6.1
    • +
    • AR-2148 Add board Bananapi M7 to vendor kernel 5.10 and 6.1
    • +
    • AR-2153 Add board FriendlyElec CM3588 NAS board
    • +
    • AR-2156 Add support for Radxa ROCK 5 ITX
    • +
    • AR-2158 Add board Radxa Zero 3 with overlays
    • +
    • AR-2171 Drop DEBUG_KERNEL/DEBUG_INFO disables; force EXPERT=y and bring back CONFIG_GPIO_SYSFS=y for all kernels
    • +
    • AR-2172 Update meson edge to 6.8 kernel
    • +
    • AR-2173 Change the way APT repository is getting updated
    • +
    • AR-2174 Thinkpad-x13s: drop steev’s kernel and switch to jhovold’s wip/sc8280xp-6.9
    • +
    • AR-2178 Fix u-boot build for Odroid C1 + fix onboard usb hub on Odroid C1
    • +
    • AR-2179 Phytium_embedded: update kernel config from phytium repo
    • +
    • AR-2180 Rockchip-rk3308-current: sakura pi rk3308b adds kernel 6.6 and 6.8 support
    • +
    • AR-2185 Switch odroidxu4-current kernel to 6.6
    • +
    • AR-2186 VIM1S/VIM4: Allow building on arm64 platform
    • +
    • AR-2187 VIM1S/VIM4: Add support for emmc + NVME/USB booting
    • +
    • AR-2196 CLI: Add command “dts-check” to validate dts files and improve board & patch development overall
    • +
    • AR-2197 Add support for allwinner T527 Avaota-A1
    • +
    • AR-2203 Rockchip-rk3308-current: add support for sakura pi rk3308b
    • +
    • AR-2208 Update sm8250: kernel add current and edge branch And Update Odin2: add kernel update hook script
    • +
    • AR-2212 H96-TVbox-rk3566 Board Bring Up
    • +
    • AR-2215 Enable vendor kernel branch on Khadas Edge 2
    • +
    • AR-2216 arm64: swiotlb: Reduce the default size if no ZONE_DMA bouncing needed
    • +
    • AR-2218 FriendlyElec CM3588-NAS: device tree fixes & improvements
    • +
    • AR-2222 Rock-5b: move edge (only) to mainline/Kwiboo u-boot 2024.04
    • +
    • AR-2226 FriendlyElec CM3588 NAS: Add mainline kernel support
    • +
    • AR-2227 mekotronics: mainline u-boot (next/Kwiboo rk3xxx-2024.04, generic-rk3588_defconfig)
    • +
    • AR-2229 rk3588: vendor-boogie-panthor
    • +
    • AR-2230 rockchip-rk3588: it’s vendor boogie panthor time (experimental)
    • +
    • AR-2235 Bump meson64 edge from 6.7 to 6.8
    • +
    • AR-2246 Add support for Radxa ZERO 3E/3W
    • +
    • AR-2250 Rock 4C+: update and cleanup boot config
    • +
    • AR-2265 cli: rewrite--patches: rewrite only patches needing a rebase
    • +
    • AR-2267 Add SK-AM68 board support
    • +
    • AR-2270 rk35xx/rockchip-rk3588: vendor: switch to armbian/linux-rockchip#rk-6.1-rkr1
    • +
    • AR-2274 Add tqma8mpxl boards support
    • +
    • AR-2276 cli: introduce rewrite-uboot-patches cli command, works similar to the kernel one
    • +
    • AR-2281 Add csc hinlink h6xk boards
    • +
    • AR-2282 Kernel: Enable *NVMe-over-TCP* for rk35xx/rk3588/rockchip64/uefi/wsl
    • +
    • AR-2289 qemu-uefi-x86: new board for virtualized environment with serial console support, kernel boot messages
    • +
    • AR-2290 cli: introduce kernel-dtb cli command, to build only DTB, and output full preprocessed dts source
    • +
    • AR-2291 cli: introduce inventory-boards cli command, for hopefully painless & useful one-board-per-line CSV output
    • +
    • AR-2292 Add board: FriendlyElec CM3588 NAS
    • +
    • AR-2293 Add vendor branch for new 6.1-rkr1 BSP vendor kernel, and keep legacy for the 5.10-rkr6 BSP vendor kernel
    • +
    • AR-2294 Phytium-embedded: add support for 4Gb Phytium Pi
    • +
    • AR-2295 Rockchip RK3588-edge: rewrite kernel patches and configs against v6.8-rc6
    • +
    • AR-2297 Refactor automatic armbian-firstlogin
    • +
    • AR-2299 Develop build config for board BananaPi M4 Zero
    • +
    • AR-2301 Develop and add Ayn Odin2 build config
    • +
    • AR-2307 Thinkpad-x13s: bump to steev’s 6.7.y; enable noble userspace; bump alsa-ucm-conf hack to master
    • +
    • AR-2308 Debootstrap: use latest git for Ubuntu/Debian debootstrap instead of host-installed
    • +
    • AR-2322 Develop PPA for (patched) aarch64 Chromium
    • +
    • AR-2327 Add support for RK3588 based Cool PI CM5 EVB
    • +
    +

    Closed Tasks

    +
      +
    • AR-2043 armbian-install should do rsync –one-file-system
    • +
    • AR-2057 enable DRBD in the kernel config of mvebu
    • +
    • AR-2077 Orangepi 5: update memory blobs
    • +
    • AR-2079 Enable ssdm autologin and apply theme
    • +
    • AR-2092 Drop repository for unsupported Releases
    • +
    • AR-2096 USB Gadget mode for rockchip 32 bit
    • +
    • AR-2101 Cleanup desktop packages
    • +
    • AR-2102 Adjusting pull request template for documentation
    • +
    • AR-2103 Disable automatic enablement of Nvidia proprietary drivers on x86
    • +
    • AR-2105 Rockchip bootscripts: `Failed to load ‘…-fixup.scr’` and `Unknown command ‘kaslrseed’`
    • +
    • AR-2110 Fix rtl8723cs for kernel 6.8
    • +
    • AR-2111 Bump rockchip edge kernel to 6.8
    • +
    • AR-2112 Bump rockchip64 edge kernel to 6.8
    • +
    • AR-2131 Builds fail for EOS distributions (for example focal)
    • +
    • AR-2132 Fail at check_loop_device: device node doesn’t exist and `$LOOP=`
    • +
    • AR-2135 Move Firefly station M2 to RK35xx family
    • +
    • AR-2136 Synchronise Rock 5 ITX from Radxa repository
    • +
    • AR-2137 Cleanup and merge OPi5 Plus device tree
    • +
    • AR-2138 Add support for the Orange Pi 5 Pro to 6.1
    • +
    • AR-2139 Add armsom sige1 support to 6.1
    • +
    • AR-2140 Add Radxa Rock 5c support to 6.1
    • +
    • AR-2141 Add dynamic-power-coefficient properties to all cores
    • +
    • AR-2142 Sync Panthor with drm-misc-next by adding missing commits
    • +
    • AR-2146 Upgrade RKNPU driver to 0.9.6
    • +
    • AR-2147 Cleanup Khadas edge 2 device tree
    • +
    • AR-2149 Use simple-audio-card for HDMI sound for rk3528
    • +
    • AR-2151 Carrying over some CM5-related commits from Radxa 3.4 branch
    • +
    • AR-2152 Add missing led gpio for hinlink h66k
    • +
    • AR-2155 Add cooling-maps and pwm-fan support for Station M3
    • +
    • AR-2159 Allow FFmpeg to capture from HDMI input
    • +
    • AR-2160 Add Ubuntu Noble support for Rockchip multimedia extension
    • +
    • AR-2161 Switch CM3588 NAS to kwiboo uboot
    • +
    • AR-2162 Declare Ubuntu Noble as supported build target
    • +
    • AR-2164 Rockchip rk3588 edge: add Hantro G1 VDPU and RGA2
    • +
    • AR-2165 Rockchip RK3588 EDGE: add generic pwm overlays from vendor kernel
    • +
    • AR-2166 rk35xx: drop vendor-boogie-panthor BRANCH; it has been integrated into vendor
    • +
    • AR-2167 Multiple boards: fixes for board file syntax / missing vars (fixing JSON matrix prepare
    • +
    • AR-2168 VIM1S/VIM4: initialize video firmware symlink
    • +
    • AR-2169 Use oibaf and v4l2 extension in desktops only
    • +
    • AR-2170 Treat sid and unstable as synonyms in distro-specific.sh
    • +
    • AR-2175 Add latest Ubuntu development branch Oracular
    • +
    • AR-2176 Armsom rk3588 boards: use radxa’s new uboot
    • +
    • AR-2177 Phytium_embedded: update phytium u-boot binary
    • +
    • AR-2182 Enable android binder to support android containers like anbox or waydroid on rk3588 edge kernel builds
    • +
    • AR-2190 Rockchip: bump rk322x u-boot to v2024.01 and support HDMI
    • +
    • AR-2191 Switch Radxa u-boot to more recent branch
    • +
    • AR-2192 Odroidn2: u-boot: fix eMMC stability
    • +
    • AR-2198 Rockchip64: cleanup rk3318-box hdmi patches
    • +
    • AR-2199 Add current kernel support for phytium-embedded
    • +
    • AR-2201 Board: h96 rk3566 HDMI sound & audio fix
    • +
    • AR-2202 Odin2 Use Custom ABL, boot from TF Card
    • +
    • AR-2204 H96-tvbox-3566 device tree fixes & improvements: wifi fix, Led and IR enable
    • +
    • AR-2206 rk35xx-vendor: enable panthor gpu driver
    • +
    • AR-2207 Rockchip64: bump rk3318-box uboot to v2024.01
    • +
    • AR-2209 Typo: while Fosstodon is the instance, Mastodon is the software used.
    • +
    • AR-2210 Rockchip64-edge: add pcie support to orangepi rk3399
    • +
    • AR-2214 Rockchip-rk3588-edge: opi5b: add support for pcie wifi
    • +
    • AR-2217 rockchip-rk3588-edge: opi5: fix typec and add support for GPU
    • +
    • AR-2219 Unlock Code and Thunderbird from all distributions
    • +
    • AR-2223 Add bluedevil for bluetooth support
    • +
    • AR-2231 rockchip: rewrite dts for rock3c
    • +
    • AR-2233 DE: KDE: add package kscreen
    • +
    • AR-2236 Rockpro64: bump u-boot to v2024.04-rc4; use binman-produced bins
    • +
    • AR-2237 Fix kernel compilation for meson-s4t7 due to Khadas vendor common_drivers not working without DEBUG enabled
    • +
    • AR-2238 Fix forced kernel options and make kernel-config consistent with rewrite-kernel-config
    • +
    • AR-2239 Rockchip RK3588 edge: enable nodes for armsom-sige7, rock 5a and h88k
    • +
    • AR-2240 armsom-sige7: add ap6275p wifi support
    • +
    • AR-2241 Rockchip-rk3588-edge: refresh cpufreq patches and auto fan control for Edge2
    • +
    • AR-2242 GH Actions: Beautify kernel hardening analysis
    • +
    • AR-2243 Khadas-vim3l/khadas-vim3: enable networking cmds in u-boot
    • +
    • AR-2244 Rockchip-rk3588-edge: khadas-edge2: add support for GPU and improve display modes
    • +
    • AR-2245 Build script: configuration: Check if ROOTFS_TYPE is supported by build host
    • +
    • AR-2247 Create linux-libc-dev when building kernel packages
    • +
    • AR-2248 bsp-cli: include BOOT_SOC to /etc/armbian-release and bsp-cli hash
    • +
    • AR-2255 Enable module snd_aloop for linux-rk35xx legacy and vendor
    • +
    • AR-2260 BananaPi M4 Zero: add gpu and uart nodes
    • +
    • AR-2262 GH Actions: Kernel hardening analysis: Exclude RISC-V configs
    • +
    • AR-2266 Expand predicted size for rootfs for abl type of images
    • +
    • AR-2269 Extend PR template when asking for documentation
    • +
    • AR-2271 rk35xx-vendor: Add kernel patching config
    • +
    • AR-2272 rk35xx-vendor: add rk3528 and lima driver support
    • +
    • AR-2275 GH Actions: Update forked-helper and add some doc on secrets in workflow’s README.md
    • +
    • AR-2277 u-boot: rewrite/rebase u-boot patches for a few boards; bump odroidm1 and orangepi3b
    • +
    • AR-2280 Show correct reason about omit tmpfs usage if FORCE_USE_RAMDISK is set
    • +
    • AR-2286 BananaPi M4 Zero: enable 8821cu and blacklist rtw88_8821cu
    • +
    • AR-2287 lib: drop old boot_logo code; keep png/gif as they’re used for plymouth
    • +
    • AR-2288 Rk35xx vendor kernel: add some network drivers
    • +
    • AR-2296 meson-6.7: Copy patches from 6.6
    • +
    • AR-2298 Prepare-host/host-release: enable noble for building
    • +
    • AR-2303 kernel: call make with INSTALL_MOD_STRIP=1 so modules are stripped
    • +
    • AR-2304 wsl2: arm64: current: DRM/FB stuff so wsl2-arm64 can be used in HyperV with video & keyboard
    • +
    • AR-2305 mekotronics 3588: add SRC_CMDLINE, for use with u-boot-menu extension
    • +
    • AR-2306 khadas-vim3/khadas-vim3l: u-boot v2024.01: enable more compression, kaslr, and led config options via hook
    • +
    • AR-2324 Optimize the kernel device tree patch for rk3399-firefly
    • +
    • AR-2325 Give shellcheck directions (to /dev/null for dynamic, to repo-relative path for static) for all sourced references
    • +
    • AR-2328 Extensions: rk-panthor: mesa-oibaf + DEFAULT_OVERLAYS=”panthor-gpu”
    • +
    • AR-2333 Set linux-image packages to provide wireguard-modules
    • +
    • AR-2335 Add chromium v4l2 encoder/decoder udev rules for all boards
    • +
    +

    Solved Bugs

    +
      +
    • AR-650 Odroid N2+ possible boot problems on eMMC
    • +
    • AR-1582 CI on our runners sometimes throws out error regarding loop devices
    • +
    • AR-2034 RockPI-S does WiFi broken on kernels >6.5
    • +
    • AR-2045 Resolve extensions rootfs encryption conflicts
    • +
    • AR-2070 VIM1S/VIM4: Booting from UHS sdcard only works intermittently
    • +
    • AR-2076 Fix random MAC address on Orangepi 5 series
    • +
    • AR-2080 Lightdm greeter is without wallpaper - black background
    • +
    • AR-2086 Home assistant supervised fails to install on Khadas VIM1S
    • +
    • AR-2090 Debootstrap is again too old for latest releases
    • +
    • AR-2094 Build failed during partprobing of /dev/loop device.
    • +
    • AR-2097 GH Actions: “Kernel hardening analysis (pull request)” kconfig-hardened-check: No such file or directory
    • +
    • AR-2098 Torrent generation fails silently
    • +
    • AR-2121 RockPi-S WiFi broken again on kernel’s >6.7
    • +
    • AR-2125 Deboostrap trixie fails at stage 2
    • +
    • AR-2143 Fix Orange Pi 5 Plus load average >= 1
    • +
    • AR-2150 Fixing deadlock issue with spin_lock in interrupt handling
    • +
    • AR-2154 Fix CEC on rk356X on tv restart
    • +
    • AR-2157 Rock-5a: pull down data-strobe to fix emmc compatibility
    • +
    • AR-2163 Restore armbian-config desktop icon
    • +
    • AR-2181 Rockchip Rock 5C: Fix RK3582 with disabled rkvdec node
    • +
    • AR-2183 Fix memory size detection for 1.5GB Orange Pi Zero 3 board on v2024.01 u-boot release
    • +
    • AR-2184 rockchip64: rework drm hunk due to mainlined patch
    • +
    • AR-2188 Make debian/trixie debootstrap-able again
    • +
    • AR-2189 Fix PCIe for RK35xx+Fix ROCK5A PCIe device tree
    • +
    • AR-2193 Hostdep fixes for Noble distutils and pyelftools removed hooks
    • +
    • AR-2200 Fixing broken device tree for H96 tvbox 3566
    • +
    • AR-2205 Fixing not operational USB port on Udoo quad
    • +
    • AR-2211 Ramlog: harden the zram mounting
    • +
    • AR-2213 Restore wireless functionality on Rock Pi S
    • +
    • AR-2220 Rockchip: update DTS patches for Orangepi R1 Plus
    • +
    • AR-2221 riscv64: fixes/skips for building (sans Docker) ON riscv64
    • +
    • AR-2224 Disable mtd-tools on Armbian Noble for armhf architecture
    • +
    • AR-2225 Fixing broken user space packages dependencies and small optimisations
    • +
    • AR-2228 RTW88: 6.x.y patches adjustment due to upstream changes
    • +
    • AR-2232 Raspberry 5 has troubles booting when faster memory access is enabled
    • +
    • AR-2234 BananaPi CM4/M2S: The fan on the unit is constantly running. So lets set thermal trip points
    • +
    • AR-2252 Rockchip RK3588 edge: fix wrong gpu node patch
    • +
    • AR-2253 Rockchip RK3588 edge: improve display modes support
    • +
    • AR-2273 Xiaomi elish fix 6.7: fixing broken dsi panel
    • +
    • AR-2283 Remove hard-coded defaults from repository management tool
    • +
    • AR-2285 Several small fixes for Banana Pi M4 Zero
    • +
    • AR-2300 Rockchip RK3588 edge: Orangepi 5 pluse: fix USB3 Host
    • +
    • AR-2309 Fixing small problems in wireless driver RTW88: RTL8822/21CU code
    • +
    • AR-2311 Meson64: fixing Librecomputer Lafrite boot failure
    • +
    • AR-2323 Resolving Armbian Noble incompatibility with Rockchip VPU extension
    • +
    • AR-2326 Radxa rock-5c: rename wireless interface name to a static one
    • +
    • AR-2329 Add new user to render group, otherwise the non-root user do not have access /dev/dri/renderD128 on RK3399
    • +
    • AR-2334 Resolve dependency issues with armbian-config
    • +
    +

    Closed Sub-task

    +
      +
    • AR-2082 Make initial devicetree to make most parts work (USB2, USB3, SD etc.)
    • +
    • AR-2083 Add Type-C support
    • +
    • AR-2084 Make AP6275P work on upstream kernel
    • +
    • AR-2085 Add Khadas Edge2 support to upstream Khadas MCU driver
    • +
    +

    v24.2.6 (2024-6-5)

    + +

    v24.2.5 (2024-4-2)

    +
      +
    • recreated images for Rpi5 due to a bug
    • +
    +

    v24.2.4 (2024-3-12)

    +
      +
    • added KDE Neon 6 desktop images for generic UEFI targets, Orangepi 5 / 5+ (with new vendor kernel 6.1.y) and Odroid M1
    • +
    +

    v24.2.3 (2024-2-26)

    + +

    v24.2.1 (2024-02-18)

    +

    Closed projects

    +
      +
    • AR-1657 Address DNS resolve with Debian Bookworm
    • +
    • AR-1797 Auto-testing: install all kernels that are defined
    • +
    • AR-1888 fix sluggish hdmi console for vim1s and vim4
    • +
    • AR-1988 Resolve Rockchip patch maintenance nightmare
    • +
    • AR-2061 Add Orangepi Zero3
    • +
    • AR-2062 Mixtile Blade 3 refactor / rockchip-rk3588 edge 6.7
    • +
    • AR-2063 Add new board of ASUS Tinker-Edge-R
    • +
    • AR-2064 Khadas VIM1S & VIM4 - 5.15 kernel bump
    • +
    • AR-2065 Add Xiaomi Mi10(umi) support
    • +
    • AR-2066 aml-s9xx-box: Update u-boot-s905x2-s922 to u-boot version 2024.01
    • +
    +

    Closed Tasks

    +
      +
    • AR-1879 JetHome: update u-boot to 2023.10
    • +
    • AR-1985 Generate new function to display download links
    • +
    • AR-1990 Move forgotten overlays from Odroid M1
    • +
    • AR-2033 revert JetHub H1/D1 wifi driver from rtw88 to vendor
    • +
    • AR-1552 Rework support for jethub devices
    • +
    • AR-1696 Khadas Edge (RK3399) has wrong name and picture
    • +
    • AR-1737 Merge Odroid M1 into rockchip64 family
    • +
    • AR-1870 Git workaround failure
    • +
    • AR-1925 Move wifi-4003-uwe5622-adjust-for-rockchip to the wireless section
    • +
    • AR-1984 Move live patch to extension
    • +
    • AR-2000 Several small maintainace tasks
    • +
    • AR-2004 Add Ubuntu Noble to the build framework
    • +
    • AR-2005 Bump all current kernels to 6.6 LTS
    • +
    • AR-2012 Please set dpkg vendor to Armbian in all images
    • +
    • AR-2016 Patchset for Rockchip (32b) needs to be ported to 6.7
    • +
    • AR-2017 Patchset for Rockchip 64b needs to be ported to 6.7
    • +
    • AR-2021 Add Home assistant extensions
    • +
    • AR-2032 LVM support, CRYPTROOT and current implementation.
    • +
    • AR-2035 Cloud-Init Supprot and Armbian First
    • +
    • AR-2050 Add support for Radxa Rock S 0
    • +
    +

    Solved Bugs

    +
      +
    • AR-1704 Bookworm Gnome lacks wallpaper withing lightdm
    • +
    • AR-1735 Command docker-shell seems to be broken
    • +
    • AR-1813 Orangepi One + fails to bring up NIC
    • +
    • AR-1861 Hashing on wireless patches seems to not work
    • +
    • AR-1908 Khadas VIM3 problem with high res displays
    • +
    • AR-1915 Extlinux / Khadas Edge 2 install to eMMC fails
    • +
    • AR-1933 Fix GitHub labeling anomaly
    • +
    • AR-1981 Edge Kernel (6.6.x) breaks WiFi and Bluetooth support for RockPI-S
    • +
    • AR-1987 Error when removing BSP package
    • +
    • AR-2003 None of the builds of Raspberry Pi 5 goes into desktop
    • +
    • AR-2007 Fix armbian.list.disabled exists
    • +
    • AR-2009 Extensions from USERPATCHES_PATH are not supported
    • +
    • AR-2010 Remove broken symlink
    • +
    • AR-2020 RK35xx is seeking for rk35xx config
    • +
    • AR-2027 Compressed images failed to upload to GitHub releases
    • +
    • AR-2034 RockPI-S does WiFi broken on kernels >6.5
    • +
    • AR-2038 KHADAS_OOWOW_BOARD_ID is not set, can’t use image-output-oowow
    • +
    • AR-2051 All installed systemd units are forcefully enabled on first boot
    • +
    • AR-2052 Cinnamon desktop doesn’t work on vim4
    • +
    • AR-2053 Desktop environment takes a long time to load on vim4
    • +
    • AR-2054 Image takes a lot of time to load on vim1s/vim4 bookworm image
    • +
    +

    v23.11.3 (2023-12-20)

    + +

    v23.11.2 (2023-12-18)

    +
      +
    • added standard support images for Raspberry Pi 5, Odroid N2/N2+, Odroid M1 due to the boards support status change
    • +
    • recreated images for Raspberry Pi 4, Nanopi R4S, Orangepi Zero2 due to several bug fixes (check commit log / newsletter for details)
    • +
    +

    v23.11.1 (2023-11-30)

    +

    Closed projects

    +
      +
    • AR-1702 Switch default login manager
    • +
    • AR-1886 Enable artifacts creation at pull request
    • +
    • AR-1924 Add support for Hikey 960
    • +
    • AR-1928 K3: Update edge kernel to v6.5
    • +
    • AR-1929 New Armbian Wallpapers
    • +
    • AR-1930 Add orangepi3b build config
    • +
    • AR-1940 Add edge kernel support for NanoPi R6S/R6C
    • +
    • AR-1941 Rework ac200 patches and config for current and edge kernel.
    • +
    • AR-1943 Add initial support for TI SK-TDA4VM board
    • +
    • AR-1951 add new device xiaomi-elish
    • +
    • AR-1957 Improve labeling system - refactor labeling logic
    • +
    • AR-1958 rk3588: configure UEFI_EDK2_BOARD_ID for all UEFI-supported boards
    • +
    • AR-1959 use GHPROXY_ADDRESS to customize ghproxy url
    • +
    +

    Closed Tasks

    +
      +
    • AR-1784 Remove FriendlyElec vendor “driver” patch in mainline
    • +
    • AR-1907 Add latest patch for eeprom support in JetHub D1+
    • +
    • AR-1811 Drop host OS-es that can’t compile Crust
    • +
    • AR-1882 Clean remaining legacy Rockchip kernels
    • +
    • AR-1897 KDE build seems to be missing features
    • +
    • AR-1913 Remove midstream kernel
    • +
    • AR-1919 Change support status to multiple selection
    • +
    • AR-1942 Add board config for Tanix TX6 tvbox
    • +
    • AR-1944 Add support for Inovato Quadra
    • +
    • AR-1945 hinlink-h28k [new board]: support new SoC Rockchip rk3528
    • +
    • AR-1946 rockchip64/edge 6.6.y: update overlay configfs patch from rpi
    • +
    • AR-1947 meson-s4t7: Add option to force 16x9 display resolution
    • +
    • AR-1948 meson-s4t7: add systemd service to enable fan in automatic mode
    • +
    • AR-1949 mekotronics-r58x-pro.wip: add new board Mekotronics R58X-Pro
    • +
    • AR-1950 mixtile-blade3: enable pci3x4 nvme boot (requires u.2 -> m.2 adapter from blade3 case kit)
    • +
    • AR-1952 Update Rock CM5 I/O board config (#5866)
    • +
    • AR-1953 Add settings & updater for KDE
    • +
    • AR-1954 add board ArmSoM-w3; with uboot-patch and updated blobs
    • +
    • AR-1956 Rockchip64: Clean up archive of all EOL kernels
    • +
    • AR-1960 VIM1S/VIM4: Add bluetooth support
    • +
    • AR-1969 BPI-CM4: Add support for the waveshare cm4-io-base-b
    • +
    • AR-1970 BPI-CM4: Enable usb support on waveshare baseboards via overlay
    • +
    • AR-1971 BPI-SM1: Removed UART_B overlay.
    • +
    • AR-1972 BPI-SM1: Add UART_A “pin-ctrl: cts rts”
    • +
    • AR-1973 Aligning display manager with the desktops
    • +
    • AR-1974 Add Ubuntu Mantic build target
    • +
    • AR-1979 Update kernel configs for Waydroid and Redroid support
    • +
    • AR-1980 xiaomi-elish: bump to kernel 6.7-rc2
    • +
    • AR-1983 xiaomi-elish: add typec pd support
    • +
    +

    Solved Bugs

    +
      +
    • AR-1641 simpledrm module prevents Mali G-31 hardware acceleration
    • +
    • AR-1832 x13s errors with bash: line 1: add-apt-repository: command not found
    • +
    • AR-1866 UWE5622 driver is broken on 6.5.y
    • +
    • AR-1876 Shallow clones CI is getting disabled due to inactivity
    • +
    • AR-1911 Raspberry Pi, upgrade fails
    • +
    • AR-1923 Rockchip kernels compilation breaking
    • +
    • AR-1932 Update firmware for Orangepi R1+ LTS
    • +
    • AR-1936 Khadas Vim1s: Fix display output
    • +
    • AR-1938 xradio: fix compilation for 6.1+
    • +
    • AR-1961 rangepi3lts: load wifi module via systemd service otherwise it crash
    • +
    • AR-1962 Restore LED triggers for each ATA port indicating disk activity in mvebu-edge
    • +
    • AR-1963 Fix broken HDMI output on rk3328
    • +
    • AR-1964 Orange Pi 3 LTS: Fix ethernet broken for some users on 6.x kernel
    • +
    • AR-1965 Fix LicheePi 4A audio problem
    • +
    • AR-1966 Khadas Vim1s: Fix monitor not detected after its turned off and on again
    • +
    • AR-1967 xiaomi-elish: update config for 6.6, and fix one bluetooth pairing issue
    • +
    • AR-1968 bootscript: meson-s4t7: fix booting on ubuntu
    • +
    • AR-1976 VIM1S: emmc 23.8.4 install fails to boot after running upgrade using beta repository
    • +
    • AR-1977 Default renderer for NetPlan is not set on Debian variants
    • +
    • AR-1982 rockpi-s still using ifconfig to set wlan MAC address
    • +
    +

    v23.08.5 (2023-10-11)

    +
      +
    • Recreated images for Khadas VIM4
    • +
    +

    Solved Bugs

    +
      +
    • AR-1887 Add fan support (fan.service) for VIM4.
    • +
    • AR-1893 Fix wifi not working on VIM4N.
    • +
    +

    v23.08.4 (2023-10-09)

    +
      +
    • Recreated images for Khadas VIM1S, Khadas VIM4
    • +
    +

    Solved Bugs

    +
      +
    • AR-1894 HDMI not working in Armbian Image on VIM1S and VIM4. Its fixed and works on most monitor now in Debian based images, Ubuntu images will also be fixed soon.
    • +
    • AR-1895 Fix HDMI monitor does not work after its turned off and on again on VIM1S
    • +
    +

    v23.08.3 (2023-09-20)

    +
      +
    • Recreated images for NanoPi Duo, Orange Pi Zero, Orange Pi Zero 2, Orange Pi 3 LTS
    • +
    +

    Closed Tasks

    +
      +
    • AR-1506 Reworked AC200 support for Allwinner current and edge kernels
    • +
    +

    Solved Bugs

    +
      +
    • AR-1280 Xradio xr819 wireless driver not available in Allwinner current and edge kernels
    • +
    • AR-1833 Slow network speed reported by iperf3 and nuttcp on Allwinner boards with Gigabit NIC
    • +
    • AR-1866 Unisoc UWE5622 wireless driver not available in Allwinner legacy, current and edge kernels
    • +
    +

    v23.08.2 (2023-09-11)

    +
      +
    • Recreated images for Orangepi 5 Plus, Bananapi M1
    • +
    +

    v23.08.1 (2023-09-01)

    +

    Closed projects

    +
      +
    • AR-1690 Add Crust to Allwinner boards to enable power management functions
    • +
    • AR-1700 Add support for most recent memory chips on BPi M5
    • +
    • AR-1723 Backport Bananapi CM4 to kernel 6.1 LTS
    • +
    • AR-1744 Provide official distro upgrades
    • +
    • AR-1838 Adding armbian-gaming as extension
    • +
    • AR-1841 Introduce grub-with-dtb extension
    • +
    • AR-1842 Add Lenovo X13S as WIP board
    • +
    • AR-1843 Khadas VIM3/VIM3L u-boot 23.07-rc4 + SPI-NOR/MTD booting support
    • +
    • AR-1850 Odroid M1 de-infest Petitboot & use Kwiboo’s 2023.10-rc2+gmac u-boot
    • +
    +

    Closed Tasks

    +
      +
    • AR-1647 Enable missing modules in sunxi64
    • +
    • AR-1718 Optimise images download build lists
    • +
    • AR-1719 Add and test 4G PCI modem on Bananapi CM4
    • +
    • AR-1722 Adjust Bananapi WiKi Pages
    • +
    • AR-1725 Update CM4 download pages
    • +
    • AR-1726 Add CM4 to auto-testing facility
    • +
    • AR-1728 Check if appropriate build targets has been generating
    • +
    • AR-1730 Make a hires photo of CM4 with modules placed on
    • +
    • AR-1780 Adjust u-boot patches to apply correctly
    • +
    • AR-1803 Enable wireless driver for MT7921U on all kernels
    • +
    • AR-1806 Generate all images that are declared in targets.yaml for single device
    • +
    • AR-1807 Test data visualisation JSON / PHP / HTML
    • +
    • AR-1824 Move Debian riscv64 from ports as its not 1st class citizen
    • +
    • AR-1826 Timezone select is too closed on status of the countries
    • +
    • AR-1834 Add gnome-calculator back to the default package base
    • +
    • AR-1836 Add SPI boot support for Rock5A
    • +
    • AR-1837 Add Orange Pi Plus
    • +
    • AR-1839 Introduce PASTE_URL to make easy to change paste service used
    • +
    • AR-1840 Add pwm-fan support to Nanopi R4S
    • +
    • AR-1844 NanoPi Duo2: enable powerbutton and ethernet
    • +
    • AR-1845 Add bluetooth-hciattach extension to Orange Pi 5
    • +
    • AR-1846 Add Collabora rockchip-rk3588 mainline based branch
    • +
    • AR-1847 Add Radxa CM5 with I/O board
    • +
    • AR-1848 Fix thermal monitoring in 6.1 kernel
    • +
    • AR-1849 NanoPC-T6 Collabora: add PCIe 3
    • +
    • AR-1851 Add Debian Trixie host and target support
    • +
    +

    Solved Bugs

    +
      +
    • AR-1539 XFCE image Rpi is missing from web download
    • +
    • AR-1570 Incomplete information in /etc/armbian-(image)-release
    • +
    • AR-1684 Synaptic search is super slow
    • +
    • AR-1707 Nightly images are not build with beta repository
    • +
    • AR-1724 CM4: Onboard WiFi and Bluetooth does not work
    • +
    • AR-1729 Userpatches support for series.conf seems broken
    • +
    • AR-1764 Some Allwinner 32bit boards hangs at boot
    • +
    • AR-1765 Recreate images that are missing in 23.05 release
    • +
    • AR-1771 Rockpi4c+ link on download page broken
    • +
    • AR-1772 RockPI-S serial console drops keystrokes
    • +
    • AR-1787 Installing Khadas Vim3 image directly to eMMC fails
    • +
    • AR-1798 Orangepi 3 / LTS and Nanopi Black 5 does not boot
    • +
    • AR-1802 Possible bug in image assembly process
    • +
    • AR-1814 Installing M2PRO to eMMC fails to boot from eMMC
    • +
    • AR-1817 Enable wireless driver for MT7915E on all kernels
    • +
    • AR-1835 mkfs.vfat command is missing in minimal images
    • +
    +

    v23.05.24 (2023-08-02)

    +
      +
    • Recreated images for: Banana M2S, Odroid C2, Khadas VIM3
    • +
    +

    v23.05.2 (2023-06-06)

    +
      +
    • AR-1765 Recreate images that are broken/missing in 23.05 release
    • +
    +

    v23.05.1 (2023-05-31)

    +

    Closed projects

    +
      +
    • AR-1516 Clean base desktops
    • +
    • AR-1536 Cleanup CLI packages list
    • +
    • AR-1543 Update RK35xx legacy kernel to 5.10
    • +
    • AR-1546 Merge all RK3588 under one kernel
    • +
    • AR-1549 Unify architecture definitions
    • +
    • AR-1557 Cleaning and adjusting CLI packages base
    • +
    • AR-1567 Generating JSON matrix
    • +
    • AR-1625 Extending JSON generation to support build matrix(es)
    • +
    • AR-1639 Enable armbian-config ORAS cache
    • +
    • AR-1693 Test as many images for upcoming 23.05 release as possible
    • +
    • AR-1700 Add support for most recent memory chips on BPi M5
    • +
    • AR-1748 Generate a sticky topic with instructions how to upgrade to Bookworm
    • +
    +

    Closed Task

    +
      +
    • AR-241 Remove NAND hacks from packaging
    • +
    • AR-345 Label trigger/workflow issue to jira
    • +
    • AR-773 Add support and bug report URL to /etc/os-release
    • +
    • AR-1512 Switch Docker pull to armbian/cache repository
    • +
    • AR-1526 UWE5622 driver consolidation for rockchip64
    • +
    • AR-1542 Add architecture property for distributions
    • +
    • AR-1573 Move UEFI kernels to 6.2, move current to legacy
    • +
    • AR-1574 Move Rpi kernels to 6.2, move current to legacy
    • +
    • AR-1575 Move Odroid M1 to 6.2.y
    • +
    • AR-1577 Move mvebu edge kernels to 6.2, current to 6.1, current to legacy
    • +
    • AR-1590 Add another package to minimal images
    • +
    • AR-1591 Armbian buster xfce image build fails at installing package numix-icon-theme-circle
    • +
    • AR-1593 Add & adjust (c) in files
    • +
    • AR-1598 Minimal builds are missing apt-utils package
    • +
    • AR-1601 Add sudo, wget and htop to minimal packages
    • +
    • AR-1602 add `fonts-noto-color-emoji` for terminal Emoji support
    • +
    • AR-1620 Effectively remove Ubuntu PRO ads
    • +
    • AR-1627 Automatically clean docker images
    • +
    • AR-1642 Could not create a username containing a number
    • +
    • AR-1645 Installer should handle input in the same way everywhere
    • +
    • AR-1651 Change Debian Bookworm into supported target
    • +
    • AR-1655 Enable CONFIG_EXFAT_FS on remaining kernels
    • +
    • AR-1656 Execute build train if kernel config changes
    • +
    • AR-1660 Enable OrangePi Zero (LTS) TV output
    • +
    • AR-1663 Add NanoPi R6S / R6C
    • +
    • AR-1664 Rebuild board selection for generating official images
    • +
    • AR-1669 Optimise PNG images we are using
    • +
    • AR-1674 Bump rockchip 32 bit edge to kernel 6.3
    • +
    • AR-1679 Drop kernel-jetson-nano-legacy
    • +
    • AR-1680 Drop kernel-rockchip-legacy
    • +
    • AR-1681 Drop kernel-rk3399-legacy
    • +
    • AR-1682 Drop kernel-rockchip64-legacy
    • +
    • AR-1683 Enable H616 CPU freq scaling
    • +
    • AR-1695 Bump rockchip64 current to 6.1.y
    • +
    • AR-1697 Add support for FriendlyElec NanoPi R4SE
    • +
    • AR-1698 Add NILFS2 fs support
    • +
    • AR-1699 Improve SD card compatibility on Radxa E25
    • +
    • AR-1706 Disable SKEL update mechanism from postinst
    • +
    • AR-1708 Improve i3-wm support
    • +
    • AR-1713 Introduce armbian-base-files artefact
    • +
    • AR-1717 Disable debug for postinst
    • +
    • AR-1747 Orangepi-r1plus-lts Network Interface logical names have changed and broken networking
    • +
    • AR-1760 Move Khadas Edge 2 to supported build targets
    • +
    • AR-1586 Consolidate RTL8723CS driver for all families
    • +
    +

    Solved Bug

    +
      +
    • AR-1443 NanoPi R4S patch overwriting mainline base DTS, needs refactored
    • +
    • AR-1474 Emoji not shown
    • +
    • AR-1523 UEFI install seems to be broken to some degree
    • +
    • AR-1528 Nanopi Neo stuck in boot loop
    • +
    • AR-1537 Missing man-db in images
    • +
    • AR-1541 UEFI swap problem and missing UUID for EFI partition
    • +
    • AR-1545 Update jethub prepackages python modules to install via apt
    • +
    • AR-1547 Jetson Nano legacy fails do build kernel
    • +
    • AR-1548 Odroid XU4 kernel compilation is failing current / edge
    • +
    • AR-1556 “No space left on device” while rsync root files to image
    • +
    • AR-1569 APT cache needs to be cleaned before closing image
    • +
    • AR-1578 Missing blobs for Riscv
    • +
    • AR-1588 Linter checking for bash shebang is incorrect
    • +
    • AR-1589 Kernel analysis is checking too many files
    • +
    • AR-1603 Broken wireless driver 8821cu-20210118
    • +
    • AR-1611 Armbian install broken when installing to USB
    • +
    • AR-1615 Bad links Orangepizero2
    • +
    • AR-1621 Raspberry Pi does not build
    • +
    • AR-1623 Armbian install fails to start on minimal images
    • +
    • AR-1628 Orange Pi Zero 2 doesn’t work
    • +
    • AR-1644 armbian-audio-config fails in minimal images; alsa-utils missing
    • +
    • AR-1648 Debian SID also split non-free firmware packages
    • +
    • AR-1650 Remote Desktop doesn’t work on desktop images
    • +
    • AR-1653 Both Firefox and Chromium are not installing from our repo
    • +
    • AR-1658 Wrong artefacts creation
    • +
    • AR-1666 File with unexpected execution rights
    • +
    • AR-1667 RockPI-S audio support is gone
    • +
    • AR-1671 Packages are being downgraded to their repo versions
    • +
    • AR-1673 uboot v2018.05-sun50iw9 compile error
    • +
    • AR-1675 Nezha has wrong manufactur attached
    • +
    • AR-1676 Can’t build linux-u-boot-radxa-e25-legacy and edge
    • +
    • AR-1677 Fix building rk322x with vendor 4.4 kernel
    • +
    • AR-1678 Can’t build Macchiatobin-doubleshot
    • +
    • AR-1685 Rock 3A is missing current kernel def
    • +
    • AR-1692 Raspberry Pi does not boot
    • +
    • AR-1705 Jethome repository missing Lunar and Bookworm index
    • +
    • AR-1714 Our packages md hash files contains temporally path
    • +
    • AR-1715 Permission problem when building with GHA
    • +
    • AR-1733 Base files does not work for riscv64 due to anomaly
    • +
    • AR-1750 Missing information in BSP about repository and build FW commit
    • +
    • AR-1751 Ubuntu Advantage is not completely removed
    • +
    +

    v23.02.1 (2023-02-25)

    +

    Closed projects

    +
      +
    • AR-1281 Armbian community automated build
    • +
    • AR-1360 Bump Rockchip64 u-boot to 2022.07
    • +
    • AR-1408 Enable EDGE branch on RK3588
    • +
    • AR-1424 Refactor release index generation
    • +
    • AR-1432 Adjust 3rd party drivers for kernel 6.1
    • +
    • AR-1435 Generate CODEOWNER on GitHub
    • +
    • AR-1444 Move repo management from the build system
    • +
    • AR-1449 Adjust action scripts to adjusted logic
    • +
    • AR-1457 Create kernel config security analysis
    • +
    • AR-1458 Enable AUFS on 6.1.y
    • +
    • AR-1460 Address corner case when looking for default route
    • +
    • AR-1461 Move hostapd from packages list
    • +
    • AR-1470 Improve new issue / request handling
    • +
    • AR-1484 Move meson64 CURRENT to 6.1.y
    • +
    • AR-1531 Add support for various HID game controllers and Waydroid
    • +
    • AR-1532 Split Bananapi M2PRO from M5
    • +
    +

    Closed Task

    +
      +
    • AR-1313 Mvebu EDGE needs to be bumped to 6.1.y
    • +
    • AR-1507 Move UWE5622 from kernel patches to misc
    • +
    • AR-1379 Add support for minimal images build in CI
    • +
    • AR-1412 Move btrfs-progs to the minimal images
    • +
    • AR-1413 Port meson sm1 emmc related patches from edge to current
    • +
    • AR-1414 Move Bananapi M5 to the previous u-boot version
    • +
    • AR-1417 Add gnome-disk-utility to the desktops
    • +
    • AR-1418 Replace nand-sata-install with symlink to armbian-install
    • +
    • AR-1419 Limit automated swap creation to 16Gb
    • +
    • AR-1421 Add nfs-common package too all except minimal
    • +
    • AR-1429 Switch to better 882xbu wireless driver
    • +
    • AR-1431 Improve audio config script
    • +
    • AR-1433 Change error reporting when linting scripts
    • +
    • AR-1434 Bump EDGE kernels to 6.1.y
    • +
    • AR-1448 Update u-boot patches for JetHub D1/D1+
    • +
    • AR-1495 Change old not supported releases to EOS
    • +
    • AR-1509 Orange Pi R1 Plus LTS add 2 device tree overlays for rk3328 uart1 and i2C0. Network and LED’s enhancements.
    • +
    • AR-1521 Add next Debian Bookworm
    • +
    • AR-1533 Disable event debugging
    • +
    • AR-1534 Add wpasupplicant to bookworm
    • +
    +

    Solved Bugs

    +
      +
    • AR-1367 PCIe is stuck at Gen1 speed even tho overlay pcie-gen2 is specificed
    • +
    • AR-1416 Missing font in Bullseye desktop cause strange fonts in Terminator
    • +
    • AR-1437 Change to GitHub workflow badge routes
    • +
    • AR-1438 rockPi-S patchset overwriting mainline device tree
    • +
    • AR-1439 Rockchip64 NanoPi patches overwriting mainline DTS
    • +
    • AR-1450 MOTD shows error on some devices
    • +
    • AR-1463 Remove code was added to the sources, which creates a mess in rk3399-rock-pi-4.dts
    • +
    • AR-1467 Raspberry Pi 3 is unbootable, 4 boots
    • +
    • AR-1476 Missing firmware on Nanopi R2S
    • +
    • AR-1482 Do not generate swap larger the 16Gb
    • +
    • AR-1522 Fix SDIO port irq level bug found in 6.0+ kernel
    • +
    • AR-1524 Cracklib check library must be present in all
    • +
    • AR-1527 Update patches for RTL8822CS
    • +
    +

    v22.11.4 (2023-01-23)

    + +

    v22.11.3 (2022-12-31)

    + +

    v22.11.2 (2022-12-09)

    +
      +
    • Re-added image for Nanopi Duo
    • +
    • Regenerated images Rock 5b (updated kernel)
    • +
    +

    v22.11.1 (2022-12-03)

    +

    Closed projects

    +
      +
    • AR-1278 Implement plymouth for kernel > 5.19.y
    • +
    • AR-1319 Upgrade Allwinner boot loader to 2022.08
    • +
    • AR-1335 Add gpiod library to armhf and arm64 server + desktop images
    • +
    • AR-1346 Grub optimisations
    • +
    • AR-1355 Add support for UEFI install to the nand-sata-install
    • +
    • AR-1362 Add Bananapi M5 to the build system
    • +
    • AR-1389 Refactor u-boot patches
    • +
    • AR-1390 Add Riscv64 support
    • +
    • AR-1399 Enable BASH linter at PR on changed files
    • +
    • AR-1402 Enable ES8316 audio properly on Radxa Rock Pi 4
    • +
    +

    Closed Task

    +
      +
    • AR-668 Using extlinux.conf instead of the legacy set of boot.scr + text files.
    • +
    • AR-949 Initial board setup
    • +
    • AR-977 Add package version number to the rootfs cache
    • +
    • AR-1034 Add missing Docker dependencies
    • +
    • AR-1112 Add ZFS repository
    • +
    • AR-1301 Add Rockpi 4C plus
    • +
    • AR-1312 Clean bootlogo patches
    • +
    • AR-1317 Remove nfs-kernel-server from default install
    • +
    • AR-1325 Deploy Chromium repo and keys to CLI images too
    • +
    • AR-1326 Add SKEL distribution to all existing users to the postinst script
    • +
    • AR-1336 Fix wallpaper not showing correct in virtual desktop
    • +
    • AR-1337 Re-enable Thunderbird email client for Debian Sid
    • +
    • AR-1338 Add Codium to Debian builds
    • +
    • AR-1342 Switch Codium with Code on x86
    • +
    • AR-1343 Update UEFI configs with latest Ubuntu desktop 22.04
    • +
    • AR-1349 Add Intel sound firmware to the desktops
    • +
    • AR-1350 Deprecating Buster and Focal
    • +
    • AR-1351 Adjust desktop support status
    • +
    • AR-1352 Add initial configuration for Terminator
    • +
    • AR-1353 Define panel shortcuts for Gnome x64 per appgroup
    • +
    • AR-1373 Port legacy kernel Rockchip Hardware Random Number Generator forward into Edge
    • +
    • AR-1376 Replace Ubuntu PRO advertisement
    • +
    • AR-1377 Add plymouth package to base images except minimal
    • +
    • AR-1388 Change purge releases action
    • +
    • AR-1404 Updated box86 and box64
    • +
    +

    Solved Bugs

    +
      +
    • AR-577 Fix USB port on Rockpi S
    • +
    • AR-1060 Freshly build image doesn’t have BRANCH info in /etc/armbian-release
    • +
    • AR-1186 Screen power savings does not work
    • +
    • AR-1265 Rock PI-S images will not boot from internal EMMC (SDNAND)
    • +
    • AR-1268 RockPI-S WiFi throughput only 300K bytes/second
    • +
    • AR-1269 RockPI WiFi assigned different MAC address on each boot
    • +
    • AR-1305 CI build wrong images in cron
    • +
    • AR-1309 Some images doesn’t want to be built, some are corrupted
    • +
    • AR-1310 Update JetHub D1 (j100) u-boot patchset
    • +
    • AR-1318 Replace expired GPG key for Github CLI
    • +
    • AR-1330 CLI images can ran out of space
    • +
    • AR-1332 Missing dependency in Docker images
    • +
    • AR-1334 Nanopi Neo3 does not have DT file in EDGE
    • +
    • AR-1340 Disable event debugging on UEFI builds
    • +
    • AR-1341 Missing wallpaper in XFCE login screen Armbian Sid
    • +
    • AR-1344 Wrong location of package uninstall
    • +
    • AR-1345 Thunderbird 32b is no more, refactoring - provide it only for 64b
    • +
    • AR-1348 Pine64H b and NPI R1 does not build u-boot
    • +
    • AR-1363 Kernel freezing in armbian-kernel might not work correctly
    • +
    • AR-1374 Hostapd needs to be workarounded
    • +
    • AR-1381 XU4: On a fresh install, after moving root to f2fs eMMC, it fails to boot
    • +
    • AR-1384 Fix RTL8822CS driver. Update build config
    • +
    • AR-1385 Ambian’s password rules are annoying
    • +
    • AR-1391 MOTD is not displaying messages correctly
    • +
    • AR-1392 Error triggered when changing BSP package
    • +
    • AR-1393 Converting to u-boot fails on riscv
    • +
    • AR-1394 Update kernel meson mmc driver to set phase clock from dts
    • +
    • AR-1395 Don’t add PPA’s to the CLI images
    • +
    • AR-1398 nand-sata-install must fail with a proper error message if the chosen mkfs.xyz is not installed
    • +
    • AR-1400 Raspberry Pi is unbootable
    • +
    • AR-1403 Wrong post install handling on install
    • +
    • AR-1405 When using PPA sources we need to run install_ppa_prerequisites
    • +
    +

    v22.08.8 (2022-10-29)

    +
      +
    • added test images for Odroid M1
    • +
    • update rockchip64 kernels
    • +
    • Regenerated images for Rockpro64, Rock64, Nanopi M4, Nanopi M4V2, Bananapi, Bananapi PRO, Bananapi M2Plus
    • +
    +

    v22.08.7 (2022-10-20)

    +
      +
    • Regenerated images for Rockpi S, Bananapi M1, PRO, M2+, M5, M64, UEFI, RPi4, ClockworkPi, Nanopi Neo3, Pinebook PRO, Renegade, Tinkerboard, OrangePi Zero, OrangePi Zero 2, OrangePi Zero plus
    • +
    • AR-1269 RockPI WiFi assigned different MAC address on each boot
    • +
    • AR-1268 RockPI-S WiFi throughput only 300K bytes/second
    • +
    • AR-1265 Rock PI-S images will not boot from internal EMMC (SDNAND)
    • +
    +

    v22.08.5 (2022-10-14)

    +
      +
    • Regenerated images for arm64 and x86 UEFI with improved installer
    • +
    +

    v22.08 (2022-08-30)

    +

    Solved Bugs

    +
      +
    • AR-1304 Boot splash is broken due to changes in kernel source
    • +
    • AR-1299 Debian throws out locale garbage at 1st login
    • +
    • AR-1296 JetHub D1 u-boot 2022.07+ bug
    • +
    • AR-1295 Switch KDE plasma to Wayland
    • +
    • AR-1294 Remove broken packages from Debian SID
    • +
    • AR-1291 Several wireless drivers break down starting with 5.19.2
    • +
    • AR-1287 Debian SID package deprecation
    • +
    • AR-1285 Primary interface problem
    • +
    • AR-1282 Upstream wireless driver is broken
    • +
    • AR-1270 RockPi cannot host a desktop because it outputs no video
    • +
    • AR-1266 Media EDGE and media CURRENT are not compiling
    • +
    • AR-1263 Fix armbian-led-state-save.sh wrong behavior on boards without gpio leds.
    • +
    • AR-1235 Fix NanoPi (rk3399) boards missing correct device tree files in rk3399-legacy
    • +
    • AR-1224 AUFS breaks on 5.15.y
    • +
    • AR-1206 Firefox from Mozilla team is n/a on Focal
    • +
    • AR-1203 Rock3a only has one recommended target
    • +
    • AR-1202 Tinkerboard has only one recommended image on the download page
    • +
    • AR-1092 Docker is not working on some 5.15.y. / 5.16.y
    • +
    • AR-1037 Missing some repository install options
    • +
    • AR-1025 Samba timeouts and throws out error
    • +
    • AR-982 Broken / invisible fonts on KDE plasma
    • +
    • AR-932 HDMI rules could make troubles on some boards
    • +
    +

    Story

    +
      +
    • AR-1303 Merging download target
    • +
    • AR-1288 Move DUT ip addresses to the database
    • +
    • AR-1284 Improve GitHub UX
    • +
    • AR-1277 Refactor rootfs cache system
    • +
    • AR-1248 Add support for month offset when creating cache
    • +
    • AR-1239 Wrong board status report at first login
    • +
    • AR-1238 Github Actions fine tuning
    • +
    • AR-1236 Add images integrity checking script
    • +
    • AR-1230 Refactor rootfs cache system
    • +
    • AR-1229 Enable code security analysis
    • +
    • AR-1220 Create nightly images directly on Github
    • +
    • AR-1130 Improve Pull request review culture and participation
    • +
    • AR-1081 Setup own mirror for kernel.org git
    • +
    • AR-580 Generate CONTRIBUTION.md at build script repository
    • +
    +

    Closed Sub-task

    +
      +
    • AR-1231 update meson64 edge kernel to 5.19
    • +
    • AR-686 Migrate beta.armiban.com to redirect
    • +
    +

    Closed Task

    +
      +
    • AR-1300 Add patches to support PiKVM
    • +
    • AR-1292 Conduct forum upgrade to latest version
    • +
    • AR-1279 Upgrade Rockchip (32 bit) edge kernel to v5.19
    • +
    • AR-1272 Move CSC targets that doesn’t build to EOS
    • +
    • AR-1251 When generating rootfs cache also store package versions
    • +
    • AR-1249 Enable Debian Sid Gnome, Budgie and Cinnamon to some powerful boards
    • +
    • AR-1237 Add a small tool to help with unifying kernel configs
    • +
    • AR-1232 JetHome: add JetHub D1p support
    • +
    • AR-1223 Desktops are missing calculator
    • +
    • AR-1211 add rock-3a emmc support
    • +
    • AR-1210 add spi boot support for rock-3a
    • +
    • AR-1182 Orange Pi 4 LTS support
    • +
    • AR-1132 Update meson64 edge&current kernels
    • +
    • AR-1127 Change build train runners to use our runners
    • +
    • AR-1073 Remove /lib/build-all.sh
    • +
    • AR-1042 Sum important information in CONTRIBUTION.md
    • +
    • AR-1028 Add support for rootfs / toolchain bind mount
    • +
    • AR-984 Integrate Khadas boards related fixes
    • +
    • AR-668 Using extlinux.conf instead of the legacy set of boot.scr + text files.
    • +
    +

    v22.05.4 (2022-07-14)

    +
      +
    • Added more desktop flavors for boards which are capable (Budgie, Gnome, KDE Plasma, Xfce and Cinnamon)
    • +
    +

    v22.05.3 (2022-06-23)

    +
      +
    • All board images have been rebuilt due to corruption found in certain images
    • +
    • Fixed Orange Pi 3 LTS bluetooth support
    • +
    • AR-1182 - Added board images for Orange Pi 4 LTS
    • +
    • AR-1228 - Upgraded bootloader to 22.04 for Rockchip family boards
    • +
    +

    v22.05 (2022-05-28)

    +

    Solved Bugs

    +
      +
    • AR-1204 - Orangepi R1plus-lts - USB3 Ethernet not working
    • +
    • AR-1202 - Tinkerboard has only one recommended image on the download page
    • +
    • AR-1199 - Orangepizero2 legacy images doesn’t boot
    • +
    • AR-1197 - Support status shows unsupported even distro variant is supported (random Focal image)
    • +
    • AR-1196 - Mainline Kernel patch breaks spidev in 5.15+
    • +
    • AR-1195 - Odroid N2 legacy kernel image does not build on Jammy
    • +
    • AR-1194 - Legacy kernels doesn’t want to be added to repository
    • +
    • AR-1193 - Images without device tree blobs fails to build via CI
    • +
    • AR-1192 - Allwinner H5 boards fails on ATF compilation
    • +
    • AR-1190 - Docker image creation fails on Jammy host
    • +
    • AR-1189 - U-boot xt-q8l-v10 legacy fails to build at CI
    • +
    • AR-1185 - Remmina is missing RDP and VNC options
    • +
    • AR-1178 - Docker images creation is broken
    • +
    • AR-1173 - Github action for generating desktops does not start
    • +
    • AR-1172 - Load induced RX bug in the r8152 driver on 5.15 and 5.17
    • +
    • AR-1171 - Budgie desktop fails to build on Jammy
    • +
    • AR-1170 - Switching to beta repository at images sometimes failed
    • +
    • AR-1169 - Chromium does not install on Jammy desktops
    • +
    • AR-1167 - Update config to support Linux 5.15.36
    • +
    • AR-1160 - When seeking changed kernels two are always marked as changed
    • +
    • AR-1151 - Kernel 5.10.y need patch adjustment for boot splash
    • +
    • AR-1149 - Current build failure due to packages
    • +
    • AR-1148 - radxa zero 512MB (no eMMC) does not load img from SD
    • +
    • AR-1141 - Ubuntu Budgie on Focal Jammy / Focal fails
    • +
    • AR-1135 - fix armbian ramlog instability
    • +
    • AR-1129 - Gnome desktop on Jammy fails to start
    • +
    • AR-1115 - Package discrepancy in Jammy
    • +
    • AR-1102 - Missing wallpapers in desktop packages
    • +
    • AR-1097 - net: stmmac: dwmac-meson8b: interface sometimes does not come up at boot.
    • +
    • AR-1091 - Wireless driver for 8822bs is not compatible with 5.15.y and up
    • +
    • AR-1061 - udev HDMI rules are causing flickering
    • +
    • AR-1033 - U-boot packages doesn’t want to be assembled with Docker
    • +
    • AR-1015 - Toolchain download only from a single source
    • +
    • AR-712 - Broken framebuffer on A20
    • +
    • AR-583 - RK3328 DMC driver needs small (hopefully) update for kernel 5.10
    • +
    • AR-191 - SATA doesn’t show up on Banana
    • +
    +

    Story

    +
      +
    • AR-988 - Add support for running x86_64 applications
    • +
    • AR-775 - Bring Marvell A3700-utils-marvell and mv-ddr-marvell.git to follow master
    • +
    • AR-273 - Improve CI autotests facility
    • +
    +

    Closed tasks

    +
      +
    • AR-1180 - Merge rk35xx-edge into rockchip64-edge
    • +
    • AR-1177 - Update only supported repositories
    • +
    • AR-1175 - Temperature monitoring for Jetson nano
    • +
    • AR-1166 - Add box86 package from 3rd party repository
    • +
    • AR-1165 - Update JetHub D1 u-boot patches
    • +
    • AR-1164 - Upgrade mvebu64 kernel to 5.17.y
    • +
    • AR-1159 - Upgrade UEFI EDGE kernels to 5.17.y
    • +
    • AR-1150 - Adjust hash calculating method
    • +
    • AR-1132 - Update meson64 edge&current kernels
    • +
    • AR-1128 - Add Nvidia driver to the x86 desktop images
    • +
    • AR-1126 - Enable desktop compilation at merge request
    • +
    • AR-1120 - Sync beta repository in the CI process
    • +
    • AR-1108 - Missing images in download section for following boards
    • +
    • AR-1076 - Add support for Orangepi 3 LTS
    • +
    • AR-1057 - Advertise recommended targets at download pages
    • +
    • AR-1008 - Update vars in amlogic u-boot script to match names of default u-boot vars
    • +
    • AR-959 - Unifying TAGS as much as possible - as universal as possible
    • +
    • AR-628 - Bump Meson64 u-boot
    • +
    • AR-296 - Remove compressed indexes for apt?
    • +
    +

    v22.02 (2022-02-28)

    +

    Solved Bugs

    +
      +
    • AR-1101 - DRM patch is failing on Rockchip
    • +
    • AR-1079 - Ubuntu archive redirector is not providing best service
    • +
    • AR-1077 - Fix RPi4 userland audio
    • +
    • AR-1069 - First login doesn’t pick up correct shell
    • +
    • AR-1065 - Twitter forum registration is not working
    • +
    • AR-1063 - X86 desktop images are not enabled in CI
    • +
    • AR-1062 - When selecting repository install u-boot might not be flashed
    • +
    • AR-1055 - Aptly repository seems to be out of business
    • +
    • AR-1048 - Rpi kernel image is not updated on upgrade
    • +
    • AR-1043 - linux-firmware repository change branch from “master” to “main”
    • +
    • AR-973 - boot building is failing after update to 2021.10
    • +
    • AR-871 - Debian SID broken wallpaper
    • +
    +

    Story

    +
      +
    • AR-1074 - Switch all CURRENT to 5.15.y and EDGE to 5.16.y
    • +
    • AR-1009 - Armbian Framework extensions and UEFI support
    • +
    +

    Closed tasks

    +
      +
    • AR-1100 - Support for Orange Pi R1 Plus LTS
    • +
    • AR-1084 - 3D support on Debian desktop
    • +
    • AR-1078 - Add additional forum plugins and adjust settings
    • +
    • AR-1068 - Add gnome-system-monitor to Focal and Jammy
    • +
    • AR-1049 - Add ZFS that supports kernel 5.15.y
    • +
    • AR-1044 - Improve Raspberry Pi support
    • +
    • AR-1041 - JetHome: fix brcm (AP6255) firmware links
    • +
    • AR-1040 - Refactor armbian-bsp-cli package creation
    • +
    • AR-931 - Using Docker image for building kernels
    • +
    • AR-893 - Cleanup rockchip64 u-boot scenarios
    • +
    • AR-757 - Adding Raspberry Pi
    • +
    • AR-586 - Implement fan controller for Nanopi M4V2
    • +
    +

    v21.08 (2021-08-31)

    +

    Solved Bugs

    +
      +
    • AR-886 - u-boot package naming
    • +
    • AR-885 - Odroid C4 / HC4 boot failure
    • +
    • AR-881 - First login shows “degraded”
    • +
    • AR-879 - RK3328 5.10 + GPU failure
    • +
    • AR-875 - Homepage fix
    • +
    • AR-874 - Add SATA fix for eBin
    • +
    • AR-873 - khadas vim3 no sound
    • +
    • AR-872 - When reverting u-boot to last known, some boards are broken
    • +
    • AR-867 - H6 Freezing
    • +
    • AR-863 - Unstable u-boot also noticed on H3 based boards
    • +
    • AR-862 - normalize RK3399 xorg configs
    • +
    • AR-857 - Qemu custom hook executing on non-targeted images
    • +
    • AR-854 - Pinebook PRO desktop doesn’t build in CI
    • +
    • AR-853 - Missing folder when making BSP file
    • +
    • AR-852 - Error when placing wallpaper
    • +
    • AR-850 - Disable XFWM compositor on XFCE4 desktop to make it run smoother
    • +
    • AR-844 - CI is picking up wrong kernel
    • +
    • AR-835 - Amlogic GLX desktop fails
    • +
    • AR-834 - edge v network weirdness
    • +
    • AR-833 - Khadas Edge V no HDMI audio
    • +
    • AR-830 - CI needs to rsync cache before start to building new images.
    • +
    • AR-829 - CI pipeline could not find some files when signing rootfs cache
    • +
    • AR-825 - Fixing I2S related errors on RK3399
    • +
    • AR-824 - Broken wifi on Station boards and kernel 5.12.y
    • +
    • AR-823 - Pine H64 doesn’t boot kernel 5.12.y
    • +
    • AR-822 - Motd false reporting of unsupported
    • +
    • AR-821 - Docker creation failed to load repository keys
    • +
    • AR-820 - Broken Odroid C2 audio patch
    • +
    • AR-819 - Wireguard repo errors
    • +
    • AR-818 - When building selected images via CI, status is changed to user-built
    • +
    • AR-816 - ZRAM is missing in Jeston Nano legacy
    • +
    • AR-780 - Nanopi R4S USB broken
    • +
    • AR-779 - New bsp package is common. Per branch changes doesn’t work anymore
    • +
    • AR-777 - Docker doesn’t install on Hirsute host
    • +
    • AR-776 - Tinkerboard legacy have some troubles booting
    • +
    • AR-774 - Orangepi Lite 2 EDGE is failing
    • +
    • AR-770 - U-boot fails to install when switching kernel to EDGE
    • +
    • AR-764 - Htop configuration exploit / vulnerability
    • +
    • AR-749 - Allwinner A20 bootloops on 5.12.y / 2021.04
    • +
    • AR-748 - Headers install broken
    • +
    • AR-747 - Deeping Desktop doesn’t want to reboot / poweroff
    • +
    • AR-744 - Nanopi K2 S905 network is broken
    • +
    • AR-741 - Pinebook pro desktop missing tweaks
    • +
    • AR-740 - Vnstat throws out garbage
    • +
    • AR-737 - Jetson nano throws out some error on boot loader compilation
    • +
    • AR-736 - Rockpi S u-boot doesn’t build on GCC.-10
    • +
    • AR-713 - Board specific desktop things are going into common desktop package
    • +
    • AR-593 - Rockpi S doesn’t boot mainline based kernel
    • +
    +

    Epic

    +
      +
    • AR-788 - Add Official Support for Some Khadas devices
    • +
    +

    Story

    +
      +
    • AR-877 - build_all needs separate logs per image
    • +
    • AR-847 - Tinkerboard 2 Support
    • +
    • AR-746 - Upgrade EDGE to 5.12.y
    • +
    • AR-734 - CSC Support for Avnet MicroZed
    • +
    • AR-214 - CI improvements
    • +
    • AR-202 - Drop packaging patches and introduce own packaging
    • +
    • AR-42 - Merge packaging patches
    • +
    +

    Closed tasks

    +
      +
    • AR-892 - Promoting Bullseye to supported
    • +
    • AR-890 - Desktop analysis with 3D enabled
    • +
    • AR-887 - Re-enable Debian Stretch repository update
    • +
    • AR-882 - Optimise image compression
    • +
    • AR-876 - Make package lists in one row
    • +
    • AR-869 - Upgrade ZFS on Linux to v2.1.0 (Focal / Bionic only)
    • +
    • AR-865 - Updating driver for 2.5G NIC on Helios64
    • +
    • AR-864 - Upgrading EDGE to K5.13.y
    • +
    • AR-859 - set - apt.armbian.com - redirect default to http instead of https
    • +
    • AR-856 - Basic RC Branch build support
    • +
    • AR-846 - Add Ubuntu 21.10 Impish
    • +
    • AR-794 - Khadas Edge-V support
    • +
    • AR-793 - Khadas VIM3L support
    • +
    • AR-792 - Preliminary Khadas VIM3 support
    • +
    • AR-791 - Khadas VIM2 support
    • +
    • AR-790 - Preliminary Khadas VIM1 support
    • +
    • AR-785 - Move mainline boot console to UART0 on Rockpi S
    • +
    • AR-784 - Add Nvidia Jetson Nano legacy kernel
    • +
    • AR-782 - Provides NFS mount functionality out of the box on CLI images
    • +
    • AR-778 - Do not pre-install obsolete apt-transport-https
    • +
    • AR-768 - Move Odroid XU4 EDGE to mainline source
    • +
    • AR-745 - chroot packaging: build script as separate function
    • +
    • AR-743 - Delay first-run autologin
    • +
    • AR-732 - Unlock Ubuntu Hirsute as supported target
    • +
    • AR-714 - Adjusting support status
    • +
    • AR-665 - rk3399 patch failure
    • +
    • AR-649 - Adding Rockchip VPU support for 5.11.y
    • +
    • AR-635 - Add legacy kernel for Zero2
    • +
    • AR-537 - Create Armbian “virtual” build target to run as VM
    • +
    • AR-519 - Odroid N2 Mainline u-boot for edge kernel
    • +
    • AR-315 - Add support for GPT table inside armbian-install
    • +
    +

    v21.05.6 (2021-06-21)

    +

    Solved Bugs

    +

    Updated images for Orangepi Zero

    +
      +
    • AR-593 - Rockpi S doesn’t boot mainline kernel
    • +
    +

    v21.05.3 (2021-05-24)

    +

    Solved Bugs

    +
      +
    • AR-780 - Nanopi R4S USB broken
    • +
    • AR-816 - ZRAM is missing in Jeston Nano legacy
    • +
    +

    v21.05.2 (2021-05-24)

    +

    Solved Bugs

    +
      +
    • AR-748 - Headers install broken
    • +
    • AR-740 - Vnstat throws out garbage
    • +
    • AR-764 - Fixing Htop security issue
    • +
    +

    Closed Tasks

    +

    ZFS updated to v2.0.4 (tested on 32bit Odroid HC1 and 64bit N2, Focal and Bionic userland) +Added Hirsute CLI images with EDGE Linux 5.12.y for most of the boards

    +

    v21.05 (2021-05-09)

    +

    Solved Bugs

    +
      +
    • AR-730 - Duplicate packages error when updating repository
    • +
    +
      +
    • AR-729 - Fix Partition Alignment for resizes and armbian-install
    • +
    +
      +
    • AR-711 - Network troubles on Nanopi K2 / Odroids
    • +
    +
      +
    • AR-709 - Tinkerboard AP crash on client connect
    • +
    +
      +
    • AR-708 - Missing library for compiling u-boot
    • +
    +
      +
    • AR-707 - Wrong keyboard code detected
    • +
    +
      +
    • AR-705 - Compilation issues when building old u-boot
    • +
    +
      +
    • AR-698 - XU4 - current kernel oddness with docker
    • +
    +
      +
    • AR-697 - Fix Meson64 Default Governor
    • +
    +
      +
    • AR-688 - Firefly boot broken
    • +
    +
      +
    • AR-674 - Users can’t change desktop wallpaper on Gnome
    • +
    +
      +
    • AR-666 - ZSH is disabled on upgrade
    • +
    +
      +
    • AR-662 - Distribution support status is not written to the /etc/armbian-release
    • +
    +
      +
    • AR-659 - Rootfs image runs out of inodes during build
    • +
    +
      +
    • AR-653 - builder issue with gnome
    • +
    +
      +
    • AR-647 - Wireless driver 8811CU is broken on 5.11.y
    • +
    +
      +
    • AR-646 - Bootsplash breaks compilation on 5.11.y
    • +
    +
      +
    • AR-644 - Wireless driver 8188 EU broken and disabled since 5.9.y
    • +
    +
      +
    • AR-636 - Odroid N2+ lost additional freq values
    • +
    +
      +
    • AR-585 - HDMI-CEC not working on rockchip64 Legacy
    • +
    +
      +
    • AR-88 - Banana Pi M3 does not boot
    • +
    +

    Finished projects

    +
      +
    • AR-694 - Create Jira-based checklist for Desktop Testing
    • +
    +
      +
    • AR-457 - Enable native arm/arm64 building
    • +
    +
      +
    • AR-454 - Additional Desktop Configurations for use with new framework
    • +
    +
      +
    • AR-444 - Improving download infrastructure Phase 2
    • +
    +
      +
    • AR-200 - Improving Desktop images
    • +
    +

    Closed Tasks

    +
      +
    • AR-714 - Adjusting support status
    • +
    +
      +
    • AR-710 - Create imx edge branch
    • +
    +
      +
    • AR-706 - Bump Allwinner u-boot to 2021.04
    • +
    +
      +
    • AR-704 - Distinguish between edge and normal image in motd
    • +
    +
      +
    • AR-696 - Improve Nvidia Jetson Nano support
    • +
    +
      +
    • AR-673 - Add few missing packages
    • +
    +
      +
    • AR-670 - Add additonal mirros for linux-firmware beside kernel source
    • +
    +
      +
    • AR-667 - Move Meson64 DEV to 5.10.y
    • +
    +
      +
    • AR-657 - Add instructions how to manual flash boot loader
    • +
    +
      +
    • AR-656 - Implement timeout on cache download
    • +
    +
      +
    • AR-654 - Fix stability issues of NanoPi M4V2 in current and dev
    • +
    +
      +
    • AR-651 - NanoPC-T4 legacy: enable USB-C DisplayPort & eDP outs
    • +
    +
      +
    • AR-648 - Resolve GPIO & PWM patches on mvebu
    • +
    +
      +
    • AR-645 - Detach rtl8812au from fixed commit ID if it builds from master
    • +
    +
      +
    • AR-643 - Bump DEV kernels to 5.11.y
    • +
    +
      +
    • AR-634 - Add Orangepi R1 Plus
    • +
    +
      +
    • AR-633 - Enable hardware PRNG/TRNG/SHA on sun8i-ce platform
    • +
    +
      +
    • AR-613 - test/beta img auto builder
    • +
    +
      +
    • AR-612 - Update pine64 install instructions
    • +
    +
      +
    • AR-600 - RK3399’s: Add multimedia and OC overlays
    • +
    +
      +
    • AR-599 - Enable HDMI-CEC and ISP1 camera support for rk3399 and rockchip64 legacy
    • +
    +
      +
    • AR-369 - Check kernel config changes
    • +
    +

    v21.02.4 (2021-04-04)

    +

    Added Nvidia Jetson Nano (community supported target)

    +

    Rebuild images for Odroid N2, H4, HC4

    +

    v21.02.3 (2021-03-09)

    +

    All kernels received upstream updates

    +

    All images has been rebuilt

    +

    Fixed reboot troubles on meson64 family (Odroid N2, C2, H4, HC4)

    +

    ZSH upgrade fixed

    +

    Type-C DP support for the NanoPC T4

    +
      +
    • AR-654 - NanoPi M4V2 stability fix for current and dev
    • +
    +

    Allwinner a20 fail to init hdmi in many cases / fixed (all images need to be rebuilt)

    +
      +
    • AR-660 - Attempt to improve stability on Helios64
    • +
    +

    v21.02.2 (2021-02-16)

    +

    All kernels received upstream updates

    +
      +
    • AR-633 - Enable hardware PRNG/TRNG/SHA on sun8i-ce platform
    • +
    +
      +
    • AR-636 - Odroid N2+ lost additional freq values
    • +
    +

    v21.02.1 (2021-02-03)

    +

    Finished projects

    +
      +
    • AR-235 - Implement Device Tree Editor
    • +
    +
      +
    • AR-476 - Add sound to Odroid N2
    • +
    +
      +
    • AR-485 - Improve multicore compilation
    • +
    +
      +
    • AR-487 - Rework download pages
    • +
    + +
      +
    • AR-546 - Added Pine64 Pinecube
    • +
    + +
      +
    • AR-568 - Add Orangepizero 2 WIP target
    • +
    +
      +
    • AR-571 - Move Meson64 DEV to 5.10.y
    • +
    +
      +
    • AR-589 - Add ZShell via armbian-zsh package
    • +
    +
      +
    • AR-590 - ZRAM Enhancements - decouple swap config from tmp
    • +
    +

    Solved bugs

    +
      +
    • AR-365 - 4k not detected properly on Amlogic, Rockchip devices
    • +
    +
      +
    • AR-440 - Errors shown at 1st login under certain conditions
    • +
    +
      +
    • AR-512 - Fix Ethernet for Opi3 and other devices with phymode for kernel 5.10
    • +
    +
      +
    • AR-514 - Download and verify not fully reliable
    • +
    +
      +
    • AR-547 - First login: adding a non-existing keyboard variant
    • +
    +
      +
    • AR-548 - mvebu DFS seems to cause system hang under high I/O
    • +
    +
      +
    • AR-557 - GCC compatibility issues
    • +
    +
      +
    • AR-559 - First login script - not all locales have UTF8 encoding
    • +
    +
      +
    • AR-565 - SATA on HC4 is not recognized
    • +
    +
      +
    • AR-570 - Improper order in getty override.conf
    • +
    +
      +
    • AR-584 - Nanopi M4V2 hangs on bluetooth loading
    • +
    +
      +
    • AR-595 - Rockpi 4B 1GB not booting
    • +
    +
      +
    • AR-605 - Booting troubles on Odroid C4 / HC4
    • +
    +
      +
    • AR-606 - Force boot script update throws out some error
    • +
    +
      +
    • AR-608 - Broken building out-of-tree modules
    • +
    +
      +
    • AR-610 - Nanopi Neo2 black sometimes nic doesn't init
    • +
    +
      +
    • AR-615 - Helios64 unstable 2.5Gbps Interface on LK5.x
    • +
    +
      +
    • AR-616 - Ubuntu Bionic ZSH / BASH changing issue
    • +
    +
      +
    • AR-617 - Locales detection doesn't work properly in some cases
    • +
    +
      +
    • AR-627 - Ubuntu update is overwriting our welcome screen
    • +
    +
      +
    • AR-629 - Odroid HC4 SATA failure
    • +
    +
      +
    • AR-631 - Orangepi Zero2 broken network
    • +
    +
      +
    • AR-632 - Desktop fails to load at second run
    • +
    +

    Closed task

    +
      +
    • AR-163 - Systematically cleanup distribution defaults
    • +
    +
      +
    • AR-206 - Improve memory performance on Renegade (roc-rk3328-cc) in current
    • +
    +
      +
    • AR-399 - Improve Pinebook PRO support
    • +
    +
      +
    • AR-467 - Enable AUFS support back
    • +
    +
      +
    • AR-472 - Added support for Ubuntu 20.10 Groovy
    • +
    +
      +
    • AR-517 - Mark Bionic builds host as deprecated
    • +
    +
      +
    • AR-520 - Move Rock64 to CSC in build script
    • +
    +
      +
    • AR-525 - Bump Rockchip 32bit to 5.9.y
    • +
    +
      +
    • AR-526 - Move mvebu-dev kernel to 5.9+
    • +
    +
      +
    • AR-551 - Update fan configuration, enable network LED and enable UPS timer
    • +
    +
      +
    • AR-552 - Re-enable UHS SDR104 mode for Helios64 and roc-rk3399-pc
    • +
    +
      +
    • AR-553 - Update builder to retrieve web seeds from mirrors api
    • +
    +
      +
    • AR-554 - OdroidN2 Ethernet Failure Pt2
    • +
    +
      +
    • AR-556 - Adding vnstat and ZFS support to MOTD
    • +
    +
      +
    • AR-558 - Switch mvebu current to K5.9
    • +
    +
      +
    • AR-563 - Improve headers compilation
    • +
    +
      +
    • AR-576 - Enabled debug on RockpiS
    • +
    +
      +
    • AR-579 - Improve (oh-my)ZSH loading speed
    • +
    +
      +
    • AR-587 - Fix kernel switching for rk3399 family
    • +
    +
      +
    • AR-594 - Upgrade Meson64 u-boot to 2020.10
    • +
    +
      +
    • AR-598 - Switch rockchip64 u-boot to 2020.10
    • +
    +
      +
    • AR-601 - Move sunxi-current to 5.10.y
    • +
    +
      +
    • AR-603 - Enable SPI boot option for roc-rk3399-pc
    • +
    +
      +
    • AR-607 - Move Meson64 Current to 5.10.y
    • +
    +
      +
    • AR-609 - Move Mvebu Current to 5.10.y
    • +
    +
      +
    • AR-611 - Switch rockchip64-current to 5.10.y
    • +
    +
      +
    • AR-614 - Upgrade ZFS packages
    • +
    +
      +
    • AR-618 - Upgrade mvebu64 current to 5.10.y
    • +
    +
      +
    • AR-619 - Bump rockchip current to 5.10.y
    • +
    +
      +
    • AR-620 - Enable network link leds for NanoPi R4S by default
    • +
    +
      +
    • AR-622 - Enable DMC for Station-M1 in current and dev
    • +
    +
      +
    • AR-623 - Enable RTC (hym8563) for Station P1 in dev and current
    • +
    +
      +
    • AR-624 - Provide an option to skip autodetection at first login
    • +
    +
      +
    • AR-628 - Bump Meson64 u-boot to 2021.01
    • +
    +
      +
    • AR-630 - Bump Odroid XU4 DEV to 5.10.y
    • +
    +

    v20.11.10 (2021-01-25)

    +

    All images rebuild due to torrent system corruption

    +

    v20.11.9 (2021-01-23)

    +

    Broken Nanopi Neo buster image rebuild, adding Station M1 and P1 legacy images, Odroid XU4 update

    +

    v20.11.8 (2021-01-17)

    +
      +
    • AR-614 - Upgrade ZFS on Focal and Buster (64bit only) to v2.0.1
    • +
    +

    v20.11.7 (2021-01-06)

    +
      +
    • AR-605 - Booting troubles on Odroid C4 / HC4
    • +
    +

    all images were rebuilt - we had a few corrupted ones in previous build

    +

    v20.11.6 (2021-01-03)

    +
      +
    • AR-601 - Move sunxi-current to 5.10.y
    • +
    +
      +
    • AR-235 - Implement Device Tree Editor in armbian-config
    • +
    +
      +
    • AR-589 - Add armbian-zsh package
    • +
    +
      +
    • AR-590 - ZRAM Enhancements - decouple swap config from tmp
    • +
    +
      +
    • AR-554 - Fix Odroid N2 Ethernet Failure
    • +
    +
      +
    • AR-556 - Adding vnstat and ZFS support to MOTD
    • +
    +
      +
    • AR-579 - Improve (oh-my)ZSH loading speed
    • +
    +
      +
    • AR-512 - Fix Ethernet for Opi3 and other devices with phymode for kernel 5.10
    • +
    +
      +
    • AR-547 - First login: adding a non-existing keyboard variant
    • +
    +
      +
    • AR-565 - Fix SATA on HC4 is not recognized
    • +
    +
      +
    • AR-595 - Fix Rockpi 4B 1GB not booting
    • +
    +

    v20.11.5 (2020-12-31)

    +

    AR-566 - Add Nanopi R4S preview images

    +

    v20.11.4 (2020-12-15)

    + +
      +
    • AR-587 - Fix kernel switching for rk3399 family
    • +
    +

    v20.11.3 (2020-12-12)

    +

    Bugfix release

    +
      +
    • AR-559 - First login script - not all locales have UTF8 encoding
    • +
    • AR-163 - Systematically cleanup distribution defaults
    • +
    • AR-206 - Improve memory performance on Renegade (roc-rk3328-cc) in current
    • +
    • AR-472 - Added support for Ubuntu 20.10 Groovy
    • +
    • AR-476 - Add sound to Odroid N2
    • +
    • AR-485 - Improve multicore compilation
    • +
    • AR-487 - Rework download pages
    • +
    • AR-508 - Add Odroid HC4
    • +
    • AR-514 - Download and verify not fully reliable
    • +
    • AR-517 - Mark Bionic builds host as deprecated
    • +
    • AR-525 - Bump Rockchip 32bit to 5.9.y
    • +
    • AR-526 - Move mvebu-dev kernel to 5.9+
    • +
    • AR-546 - Added Pine64 Pinecube
    • +
    • AR-547 - First login: adding a non-existing keyboard variant
    • +
    • AR-548 - mvebu DFS seems to cause system hang under high I/O
    • +
    • AR-551 - Update fan configuration, enable network LED and enable UPS timer
    • +
    • AR-552 - Re-enable UHS SDR104 mode for Helios64 and roc-rk3399-pc
    • +
    • AR-553 - Update builder to retrieve web seeds from mirrors api
    • +
    • AR-556 - Adding vnstat and ZFS support to MOTD
    • +
    • AR-557 - GCC compatibility issues
    • +
    • AR-558 - Switch mvebu current to K5.9
    • +
    • AR-563 - Improve headers compilation
    • +
    • AR-565 - SATA on HC4 is not recognized
    • +
    • AR-568 - Add Orangepizero 2 WIP target
    • +
    • AR-570 - Improper order in getty override.conf
    • +
    • AR-571 - Move Meson64 DEV to 5.10.y
    • +
    +

    v20.11.1 (2020-12-04)

    +
      +
    • AR-551 - Update fan configuration, enable network LED and enable UPS timer
    • +
    • AR-565 - SATA on HC4 is not recognized +Updated Odroid C4/HC4, Helios64, Rockpi 4* images and rockchip64 kernels
    • +
    +

    v20.11 (2020-11-24)

    +

    Finished projects

    +
      +
    • AR-2 - Improving download infrastructure Phase 1
    • +
    • AR-151 - Integrate JMCCs Multimedia script
    • +
    • AR-230 - Decide what to do with TVboxes
    • +
    • AR-412 - Update Odroid XU4 kernels
    • +
    • AR-424 - Improve HTOP config
    • +
    • AR-456 - Upgrading Allwinner u-boot to 2020.10
    • +
    • AR-476 - Add sound to Odroid N2
    • +
    • AR-485 - Improve multicore compilation
    • +
    • AR-508 - Add Odroid HC4
    • +
    • AR-509 - Upgrade meson64 to 5.9.y
    • +
    • AR-510 - Move meson (Odroid C1) to 5.9.y
    • +
    • AR-532 - Move Odroid C4 from legacy u-boot toward mainline
    • +
    +

    Solved bugs

    +
      +
    • AR-314 - Links to SHA files at download pages are wrong
    • +
    • AR-372 - Meson64 Reboot failure kernel 5.7
    • +
    • AR-373 - Rock64 no HDMI (must be unplugged)
    • +
    • AR-382 - Fix zram creation on bigger memory devices
    • +
    • AR-391 - Warning a reboot is needed doesn’t go away after reboot
    • +
    • AR-407 - Bug in first login script
    • +
    • AR-417 - HTOP in Bullseye needs higher package version
    • +
    • AR-420 - GPIO SPI patch is failing on Rockchip64
    • +
    • AR-422 - Improper version showing at upgrade
    • +
    • AR-425 - Resize is finished but message doesn’t disappear
    • +
    • AR-428 - Firefox initial config has different location then ESR variant
    • +
    • AR-436 - Rockpi S reports some error in postinst scripts
    • +
    • AR-437 - MOTD cosmetic issue
    • +
    • AR-439 - Automated rebuilds set image status to USER_BUILT
    • +
    • AR-441 - Odroid C4 legacy bootscript problem
    • +
    • AR-452 - Fix first boot locales selection and add desktop lang switching
    • +
    • AR-459 - Missing package libreoffice-style-tango from Bullseye desktop
    • +
    • AR-471 - Mitigate Git server failures
    • +
    • AR-482 - Htop doesn’t show CPU speed to normal user but shows properly to root
    • +
    • AR-484 - Odroid C4 refuse to boot
    • +
    • AR-491 - LEDs on Helios4 not working
    • +
    • AR-493 - Patches are not creating
    • +
    • AR-494 - Fix armbian-hardware-opitimization not being run
    • +
    • AR-505 - armbian-hardware-optimization: eth0 tweak applied before it is appear on /proc/interrupts
    • +
    • AR-527 - Rockchip 32bit sources were removed
    • +
    • AR-528 - Improve creating images from repository
    • +
    • AR-529 - Z28 PRO device tree doesn’t exists in mainline
    • +
    +

    Closed tasks

    +
      +
    • AR-284 - Discuss if there is a cleaner way to install Chromium
    • +
    • AR-350 - Switch rock64 to mainline u-boot
    • +
    • AR-351 - Switch rockpro64 to mainline u-boot
    • +
    • AR-363 - Switch mvebu current to K5.8.y
    • +
    • AR-380 - Revisit RTL8812AU driver
    • +
    • AR-387 - Switch from rk3399-bluetooth service to btbcm for loading firmware/patchram in dev/current
    • +
    • AR-388 - XU4 - Introduce new Mem freq scaling patch and re-enable
    • +
    • AR-390 - Add Radxa Rockpi 4C
    • +
    • AR-400 - Enable overlays in rockchip64-legacy
    • +
    • AR-401 - Enable creation of SPI flash u-boot image for ROCK Pi 4
    • +
    • AR-403 - Enable overlays in rk3399-legacy
    • +
    • AR-404 - Switch renegade to mainline u-boot
    • +
    • AR-409 - Move imx6 current kernels to 5.8.y
    • +
    • AR-413 - Improve reliability of Helios64’s eMMC module
    • +
    • AR-415 - Improve reboot reliability for Helios64
    • +
    • AR-416 - Move Rockchip 32bit to 5.8.y
    • +
    • AR-419 - Add dedicated DT for Nanopi Neo3
    • +
    • AR-445 - systemd-journal not rotated with armbian-ramlog
    • +
    • AR-458 - Update board support statuses
    • +
    • AR-461 - Add Armbian to Neofetch
    • +
    • AR-462 - Adapt helios64 device tree name to match upstream Linux
    • +
    • AR-464 - Move Libre Computer Renegade to mainline u-boot
    • +
    • AR-472 - Added support for Ubuntu 20.10 Groovy
    • +
    • AR-473 - Add interactive option to use precompiled packages from Armbian repository
    • +
    • AR-477 - Advanced recovery options for rockchip64 boards
    • +
    • AR-483 - Fix analog (3.5 jack) audio on ROCK Pi 4C
    • +
    • AR-490 - Enable RTC on Odroid N2
    • +
    • AR-495 - Allow building images with kernels 5.8.17+ and 5.9.2+
    • +
    • AR-499 - Enable Watchdog for G12/Odroidn2
    • +
    • AR-504 - Helios64: Switch fusb302 driver to mainline and enable DP over TypeC
    • +
    • AR-511 - Switch rockchip64-current to linux 5.9.y
    • +
    • AR-513 - Move Odroid XU4 kernels up
    • +
    • AR-515 - Upgrade imx6 to 5.9.y
    • +
    • AR-521 - Exchange mv with rsync
    • +
    • AR-522 - Allow setting MTU for Rockchip64’s dwmac interface
    • +
    • AR-523 - enable CONFIG_TARGET_CORE for iSCSI target support
    • +
    • AR-524 - Upgrade rockpis legacy kernel
    • +
    • AR-531 - Check why disabling one update-initramfs breaks Ubuntu initrd making on update
    • +
    +

    v20.08.22 (2020-11-8)

    +

    Added WIP images for Odroid HC4 +Updated images for Odroid C4, N2, C2, Lafrite, Lepotato, KVIM1

    +

    v20.08.13 (2020-10-19)

    +
      +
    • AR-363 - Switch mvebu current to K5.8.y
    • +
    • AR-466 - Enable Recovery button on Helios64
    • +
    • AR-416 - Move Rockchip 32bit to 5.8.y
    • +
    • AR-476 - Add sound to Odroid N2 +update all kernels +Rebuild images for Helios4, Helios64 and Odroid N2
    • +
    +

    v20.08.11 (2020-10-16)

    +
      +
    • AR-465 - Helios64 cannot boot from eMMC +enable Ubuntu 20.10 Groovy as a CSC build option (need build parameter EXPERT=”yes”) +update u-boot loader to 2020.10 on Allwinner platform +update all kernels +update images for Helios 64 +add option to build images from prebuild packages from repository which drastically improves build time in case you don’t need to rebuild kernel
    • +
    +

    v20.08.8 (2020-10-05)

    +
      +
    • AR-463 - Improve Helios64 Stability, updated images +Adapt Helios64 devicetree name to match upstream Linux
    • +
    +

    v20.08.4 (2020-09-23)

    +
      +
    • AR-399 - Improve Pinebook PRO support, updated images +Updated Helios64 images
    • +
    +

    v20.08.3 (2020-09-21)

    +
      +
    • updated mainline kernel based images to Linux 5.8.10
    • +
    • all other kernels updated to respective latest version
    • +
    • improved htop with showing network status dynamically, GPU temp, improved CPU speed display
    • +
    • fixed usbip for sharing usb over network
    • +
    • fixed Odroid C4 boot script bug; adding normal and higher CPU speeds
    • +
    • added many improvements for Helios64
    • +
    • enabled GPU temperatures in htop for XU4, meson64 (Odroid N2/N2+) and rockchip64/32
    • +
    • fixed initial configuration for Firefox
    • +
    • fixed tx offloading for Rockchip64 NIC’s
    • +
    • move rockchip 32bit to 5.8.y (Tinkerboard / MiQi)
    • +
    • improved RK3399 stability by mingling OPP
    • +
    • fixed a bunch of bugs related to encrypted root filesystem
    • +
    • enabled hardware watchdog support for mvebu64 / Espressobin
    • +
    • cosmetic fixes to motd
    • +
    • enabling I2S and spdif on Nanopi Neo3 by default
    • +
    • fixes wrong memory calculation on ZRAM display
    • +
    • fixing firstlogin bug preventing running xrdp
    • +
    • move Espressobin kernel to 5.8.y
    • +
    • adjust / fix Kali Linux wifi injections patches
    • +
    +

    Known bugs:

    +
      +
    • Some Rockpro64 boards have troubles with upgrade
    • +
    • Bananapi M3 eMMC can’t boot from eMMC (solution is available)
    • +
    • H6 stability issues on some boards
    • +
    • RockpiS shows some error on upgrade but upgrade suceeds
    • +
    • 4K and audio on mainline based meson64 boards
    • +
    +

    v20.08 (2020-08-20)

    +

    Finished projects

    +
      +
    • AR-45 - Make first login more user friendly
    • +
    • AR-71 - Create a document: How we will use Jira
    • +
    • AR-182 - Unify / merge kernel configs
    • +
    • AR-201 - Introduce CI autotest facility
    • +
    • AR-227 - Move Espressobin current to K5.6
    • +
    • AR-313 - Ability to work in offline mode
    • +
    • AR-320 - Initial support for Rockpi E
    • +
    • AR-324 - Add Rockchip RK322X SoC support
    • +
    • AR-328 - Meson64 move current to 5.7.y
    • +
    • AR-329 - Switch sunxi dev target to kernel 5.7
    • +
    • AR-331 - Enable kernel boot splash as an option
    • +
    • AR-335 - Improve patch making
    • +
    • AR-392 - Add Odroid N2+
    • +
    • AR-402 - Add Helios64
    • +
    +

    Solved bugs

    +
      +
    • AR-282 - Rockpi 4B 1Gb doesn’t boot modern kernel / u-boot
    • +
    • AR-295 - Odroid C2: no more USB devices after upgrade
    • +
    • AR-298 - Missing default SElinux policy
    • +
    • AR-303 - Create a download page for BPI M2 zero
    • +
    • AR-305 - K-worker creates load on Allwinner devices
    • +
    • AR-319 - Armbian config failed to switch kernels
    • +
    • AR-330 - Shell check bugs
    • +
    • AR-332 - When making all kernels - building sometimes fails
    • +
    • AR-337 - Odroid XU4 Memcopy Slow on all Kernel 5.x 80MB/sec instead of 370+MB/sec
    • +
    • AR-338 - Bananapi R2 does not boot at all
    • +
    • AR-340 - Fix WiFi on Nanopi M4V2
    • +
    • AR-348 - Confirm RK3399 TcpOffloading bug
    • +
    • AR-352 - Fix Random MAC on H3 boards
    • +
    • AR-354 - Support User Provided EDID Firmware
    • +
    • AR-355 - backport Linux v5.8 fbtft/fb_st7789v invert colors, proper gamma
    • +
    • AR-356 - Building multiple u-boot targets breaks
    • +
    • AR-371 - CPU frequency scaling broken on H6
    • +
    • AR-378 - Increase address room for initial ramdisk
    • +
    • AR-381 - selinux-policy-default missing on Debian Bullseye
    • +
    • AR-393 - Ask for setting locale at first run
    • +
    +

    Closed tasks

    +
      +
    • AR-28 - Added new GCC compilers
    • +
    • AR-225 - Introduce PACKAGE_LIST for BOARD and FAMILY
    • +
    • AR-300 - Enable HDMI audio for OrangePi 4
    • +
    • AR-317 - Move Odroid XU4 dev to mainline + patches
    • +
    • AR-318 - Upgrade Odroid XU4 legacy kernel
    • +
    • AR-321 - Upgrade Meson (C1) current to 5.7.y
    • +
    • AR-323 - Allow install to SD NAND for Rockpi S
    • +
    • AR-326 - Make USB3 support of ROCK Pi E on par with other rk3328 boards
    • +
    • AR-327 - Bump imx6 current kernel to 5.7.y
    • +
    • AR-333 - Update Odroid XU4 kernels
    • +
    • AR-334 - Cleanup boot environment files
    • +
    • AR-336 - Add support for cheap 2.5GB USB network dongles
    • +
    • AR-341 - Follow-up N2 CPU Affinity
    • +
    • AR-349 - Update mainline u-boot to v2020.07 for rockchip64 and rk3399
    • +
    • AR-357 - IRQ affinity improvements for G12B
    • +
    • AR-358 - Added initial support for Neo 3
    • +
    • AR-361 - Update Odroid XU4 boot.ini
    • +
    • AR-362 - HDMI sound support for Allwinner A10, A20, A31
    • +
    • AR-364 - Change sunxi legacy to 5.4.y, current to 5.7.y
    • +
    • AR-366 - Move rockchip/64 current to 5.7.y
    • +
    • AR-383 - Upgrades for Tapatalk plugin
    • +
    • AR-389 - Add PACKAGE_LIST_BOARD_REMOVE option
    • +
    +

    v20.05.7 (2020-07-02)

    +
      +
    • AR-308 - Disable HDMI in u-boot for rk3399 boards
    • +
    • AR-338 - Bananapi R2 does not boot at all
    • +
    • AR-337 - Odroid XU4 Memcopy Slow on all Kernel 5.x 80MB/sec instead of 370+MB/sec +Update images for: NanoPC T4, Nanopi M4,Nanopi M4v2, Nanopi Neo4, Orangepi 4, Firefly RK3399, Bananapi R2, Odroid XU4
    • +
    +

    v20.05.6 (2020-06-19)

    +
      +
    • AR-324 - Add Rockchip RK322X SoC support
    • +
    • AR-320 - Initial support for Rockpi E
    • +
    • AR-323 - Allow install to SD NAND for Rockpi S
    • +
    +

    v20.05.5

    +

    never released/skipped

    +

    v20.05.4 (2020-06-16)

    +
      +
    • AR-311 - Initrd on Focal can get corrupted followup fix
    • +
    +

    v20.05.3 (2020-06-10)

    +
      +
    • AR-300 - Enable HDMI audio for OrangePi 4
    • +
    • AR-305 - K-worker creates load on Allwinner devices
    • +
    • AR-282 - Rockpi 4B 1Gb doesn't boot modern kernel / u-boot
    • +
    +

    v20.05.2 (2020-06-05)

    +
      +
    • AR-294 - Initrd on Focal can get corrupted
    • +
    +

    v20.05.1 (2020-05-31)

    +

    Kagu

    +

    Finished projects

    +
      +
    • AR-108 - Upgrade remaining kernels to 5.4.y
    • +
    • AR-158 - Update 3rd party wireless drivers
    • +
    • AR-159 - Switch fake-hwclock to hardware RTC on mvebu family
    • +
    • AR-168 - Add NanoPi R2S board support
    • +
    • AR-180 - Update Wireguard drivers on kernels below 5.4.y
    • +
    • AR-184 - Improve slow booting on Rockchip RK3399 devices
    • +
    • AR-185 - Change download images compression format
    • +
    • AR-190 - Update wireless driver for RTL88x2BU
    • +
    • AR-196 - Upgrade u-boot to 2020.04 where possible
    • +
    • AR-201 - Introduce CI autotest facility
    • +
    • AR-207 - Merge rockpis-dev into rockchip64
    • +
    • AR-208 - Consolidate u-boot variants for mvebu family
    • +
    • AR-210 - Add support for more HDMI resolutions on Rockchip RK3288 devices
    • +
    • AR-215 - Move meson64 dev branch to 5.6.y
    • +
    • AR-221 - Upgrade imx6 current to 5.6.y
    • +
    • AR-222 - Port Docker image building to Ubuntu 20.04
    • +
    • AR-226 - Add Hardkernel Odroid C4 mainline u-boot / kernel
    • +
    • AR-236 - Attach Meson64 CURRENT to 5.6.y
    • +
    • AR-238 - Updating hostapd, PSD and theme package in repository
    • +
    • AR-247 - Revitalise Udoo board
    • +
    • AR-250 - Improve usage of external patches
    • +
    • AR-253 - Add prerm script for headers
    • +
    • AR-254 - Add Banana Pi M2 Zero
    • +
    • AR-257 - Bring Odroid C1 back from the EOL with latest upstream kernel
    • +
    • AR-260 - Add Nanopi A64 board support
    • +
    • AR-261 - Add Rockpi S mainline board support
    • +
    • AR-262 - Move Allwinner development branch to 5.6.y
    • +
    • AR-278 - Add snap free Chromium to Ubuntu Focal
    • +
    • AR-279 - Add Hardkernel Odroid C4 stock kernel
    • +
    +

    Solved bugs

    +
      +
    • AR-109 - Upgrade is not done properly on some boards
    • +
    • AR-165 - Instability with Rock64 and Rock PRO
    • +
    • AR-177 - No serial gadget console on Nanopi Neo2 black
    • +
    • AR-181 - Odroid N2 crashes during USB rsync backups
    • +
    • AR-198 - Olimex Lime 2 doesn’t boot from eMMC
    • +
    • AR-204 - CPUfreq defaults missing on update
    • +
    • AR-205 - No sound output with OrangePi 4 in dev and current
    • +
    • AR-211 - Chrony fails to start on Ubuntu Focal
    • +
    • AR-212 - Random MAC on Nanopi R2S
    • +
    • AR-220 - Disable 3D support in Bionic due to broken mesa packages
    • +
    • AR-231 - Unstable stmmac network driver on Meson64
    • +
    • AR-237 - Desktop install on Ubuntu Focal installs Gnome3 desktop
    • +
    • AR-239 - Chrony fails to start on Focal
    • +
    • AR-240 - Broken VFAT kernel upgrade
    • +
    • AR-244 - Thermal throttling on H5 doesn’t work properly
    • +
    • AR-245 - Hostapd doesn’t go up
    • +
    • AR-248 - Odroid C4 CPU speed is limited to 1.5Ghz
    • +
    • AR-249 - Problems with CI testings
    • +
    • AR-251 - Fix kernel 5.7.y packages patch
    • +
    • AR-255 - Fix Debian mirrors URL
    • +
    • AR-263 - Fix audio on Renegade
    • +
    • AR-269 - Add correct CPU regulator configuration for the NanoPI R1
    • +
    • AR-274 - Add missing iozone3 package to the minimal image
    • +
    • AR-277 - Distinguish nightly and stable images at the download pages
    • +
    • AR-286 - Armbian-resize-filesystem fails on first run due to missing fdisk in Bullseye
    • +
    • AR-287 - Make sure cryptsetup-initramfs is installed in any case
    • +
    +

    Closed tasks

    +
      +
    • AR-150 - Disable Stretch image creation for Helios4 and Clearfog
    • +
    • AR-157 - Add Ubuntu Focal 20.04 as a supported build host
    • +
    • AR-186 - Blacklist 3D engine on headless images
    • +
    • AR-189 - Move wireless driver for 8189ES from patch to git
    • +
    • AR-195 - Adding Ubuntu 20.04 to all builds
    • +
    • AR-209 - Disable CONFIG_VIDEO_DE2 in u-boot for Allwinner devices
    • +
    • AR-213 - Make manual for .xz images and check their authentication
    • +
    • AR-228 - Enable audio and USB on Nanopi A64
    • +
    • AR-229 - Bump with AUFS for DEV kernels
    • +
    • AR-232 - Switch Odroid XU4 DEV branch to Libreelec branch
    • +
    • AR-234 - Disable ZSH update prompt on every two weeks
    • +
    • AR-242 - Enable SELinux
    • +
    • AR-252 - Improve source code cleaning
    • +
    • AR-258 - Enables PCIE PHY with Mezzanine NVME
    • +
    • AR-259 - Add mp8859 regulator to current for RK3399-ROC-PC
    • +
    • AR-264 - Enable RTL8723DS WiFI driver
    • +
    • AR-265 - Remove Xenial from supported host OS
    • +
    • AR-266 - Fix dependency for native building on Linux Mint and Debian Buster
    • +
    • AR-267 - Enable Cedrus video acceleration on Allwinner kernels
    • +
    • AR-268 - Add higher clock for Allwinner H6
    • +
    • AR-270 - Add support for alternate console UARTs in Allwinner H3 u-boot
    • +
    • AR-271 - Lower DDR clock rate to 504MHz for H5 boards
    • +
    • AR-280 - Update CONF, CSC and WIP statuses according to support level
    • +
    • AR-285 - Improve thermal throttling on Allwinner H6
    • +
    • AR-288 - Add vendor name to the board config files
    • +
    +

    v20.02.12 (2020-04-27)

    +
      +
    • Added preview images for Odroid C4
    • +
    +

    v20.02.8 (2020-03-26)

    +
      +
    • update kernels with upstream versions, synchronise and test kernel sources download
    • +
    +

    v20.02.7 (2020-03-26)

    +
      +
    • Updated images for Rockpi S, Odroid XU4 and FriendlyARM Nanopc T3, T3+, M3, Fire3
    • +
    +

    v20.02.6 (2020-03-23)

    +
      +
    • Updated images for Rockpi S and Orangepi 4
    • +
    • Updated armbian-config (fixed OMV installer)
    • +
    +

    v20.02.5 (2020-03-19)

    +
      +
    • Updated images for Orangepi 4, Bananapi and Rockpi S
    • +
    +

    v20.02.4 (2020-03-18)

    +
      +
    • Added images for Nanopi R2S and Bananapi M2 Zero
    • +
    • Kernel update for Odroud XU4
    • +
    +

    v20.02.3 (2020-02-21)

    +
      +
    • Updating images for Le potato, Khadas Vim1,La Frite, Nanopik2 S905, Odroid N2/C2 - fixing audio
    • +
    • Updating images for Orangepi 4 - boot loader problem
    • +
    +

    v20.02.2 (2020-02-18)

    +

    Chiru

    +

    Tasks

    +
      +
    • AR-46 - Support for single function run
    • +
    • AR-47 - Adding Docker shell support
    • +
    • AR-49 - Move sunxi kernel to 5.4.y
    • +
    • AR-79 - Check and adjust AUFS patch for 5.4.y
    • +
    • AR-80 - Move imx6 to 5.4.y
    • +
    • AR-81 - Enable Meson64 DEV at 5.4.y
    • +
    • AR-82 - Move Mvebu64 / Espressobin dev kernel to 5.4.y
    • +
    • AR-84 - Move rockchip64 current to 5.4.y
    • +
    • AR-85 - Adjusted Sunvell R69
    • +
    • AR-90 - Add support for Nanopi M4 v2
    • +
    • AR-92 - Enable stable MAC address from cpuid on rk3399
    • +
    • AR-96 - Update Xradio wireless driver
    • +
    • AR-97 - Tag supported builds properly at download pages
    • +
    • AR-98 - Enable missing Kuberenetes kernel dependency
    • +
    • AR-100 - Add Debian Bullseye and Ubuntu Focal
    • +
    • AR-112 - Enabled internal WLAN on RockPi S
    • +
    • AR-113 - Install wireguard tools only when selected
    • +
    • AR-114 - Enable audio codec on Orangepi Win
    • +
    • AR-115 - Add drivers for Realtek RTL8811CU and RTL8821C chipsets
    • +
    • AR-116 - Remove annoying debug message filling logs on 8189es
    • +
    • AR-117 - Add Pine H64 model B
    • +
    • AR-124 - Enable wireless on Rockpi-S
    • +
    • AR-127 - Refactoring wifi patches
    • +
    • AR-128 - Adding WIP support for Pinebook PRO
    • +
    • AR-129 - Move NanopiM4 V2 and Pine H64 under supported
    • +
    • AR-134 - Update AUFS version on Odroid XU4 and Nanopi Fire3/T3/T3+
    • +
    • AR-138 - Update RK3399 legacy kernel (Nanopi M4, T4, Neo4) to latest upstream version
    • +
    • AR-139 - Nanpi R1 - move primary serial console to ttyS1 which is on the chassis
    • +
    • AR-143 - Create OpenHab installation instructions for their official documentation
    • +
    • AR-146 - Update rockchip-legacy to most recent upstream kernel version
    • +
    • AR-147 - Enable analogue audio on Allwinner H6
    • +
    • AR-148 - [ mvebu-current ] Fix cpufreq (dynamic frequency scaling)
    • +
    • AR-149 - [ mvebu-current ] Fix pcie issues
    • +
    • AR-153 - Enable USB3 for Rock64/Renegade with RK3328 on mainline kernel
    • +
    • AR-154 - Add analogue audio driver to Allwinner H6
    • +
    • AR-155 - Enable Cedrus video acceleration support on Allwinner boards
    • +
    • AR-167 - Add upstream patches for Odroid XU4
    • +
    • AR-172 - USB3 Support for Rockchip
    • +
    +

    Bugs

    +
      +
    • AR-74 - User patches directories not created
    • +
    • AR-76 - Rockchip64 missing CPU_MIN variable
    • +
    • AR-77 - Wrong board name variable for Orangepi RK 3399
    • +
    • AR-83 - Packaging patch broken for kernel 5.4.y
    • +
    • AR-86 - CPU freq scaling for H6 doesn't work in K5.4
    • +
    • AR-88 - Banana Pi M3 does not boot
    • +
    • AR-89 - Tinkerboard S doesn't start from eMMC
    • +
    • AR-91 - Broken Allwinner overlays
    • +
    • AR-94 - Espressobin v7 with 2gb of ram fail to boot
    • +
    • AR-102 - Missing packaging patch for Rockpis legacy kernel
    • +
    • AR-103 - PPA way of adding sources are failing on Ubuntu
    • +
    • AR-104 - 32bit rust compiler doesn't run new kernels
    • +
    • AR-105 - Orangepi Zero Plus 2 doesn't boot
    • +
    • AR-106 - Wireguard breaks building on 5.4.y
    • +
    • AR-107 - Improve compiler and rootfs download process
    • +
    • AR-110 - Missing Bionic image for Nanopi Neo Plus2
    • +
    • AR-111 - Some versions of Orangepi Win does not boot modern kernel
    • +
    • AR-118 - NanoPi M4V2 ethernet partialy broken in one side
    • +
    • AR-123 - OpenHAB2 installation is failing
    • +
    • AR-125 - Wireless driver for 8188EUS breaks on K4.14
    • +
    • AR-126 - Nanopi M3/Fire3/PC3 compilation breaks
    • +
    • AR-130 - Instability with various A64 boards
    • +
    • AR-131 - Add support for 3rd version of Pinebook A64 panel
    • +
    • AR-133 - Odroid XU4 legacy kernel images instability
    • +
    • AR-141 - Odroid XU4 current with kernel 5.4.y seems unstable
    • +
    • AR-142 - Cryptsetup disk encryption build feature broken
    • +
    • AR-144 - Tinkerboard break booting
    • +
    • AR-145 - Missing HDMI audio on H3 boards
    • +
    • AR-152 - Display issues with Bionic Mesa update
    • +
    • AR-164 - Htop package does not build in qemu under Ubuntu Focal 20.04
    • +
    • AR-166 - Rootfs cache number creates a window of 12h when users are forced to rebuild cache
    • +
    • AR-170 - Wireless not connecting for SBCs
    • +
    • AR-171 - Fix broken loading process on MiQi
    • +
    • AR-173 - Fix makefile of kernel headers 4.4.210 for rk3399
    • +
    • AR-174 - Teres Keyboard Not Working
    • +
    +

    Stories

    +
      +
    • AR-48 - Bump u-boot to 2020.01 on RK3399 boards
    • +
    • AR-156 - WIP orangepi 4 preliminary support
    • +
    +

    v19.11.3 (2019-11-20)

    +

    Tasks

    +
      +
    • AR-1 - Adding support category for distributions
    • +
    • AR-4 - Remove Allwinner legacy
    • +
    • AR-5 - Drop Udoo family and move Udoo board into newly created imx6 family
    • +
    • AR-9 - Rename sunxi-next to sunxi-legacy
    • +
    • AR-10 - Rename sunxi-dev to sunxi-current
    • +
    • AR-11 - Adding Radxa Rockpi S support
    • +
    • AR-13 - Rename rockchip64-default to rockchip64-legacy
    • +
    • AR-14 - Add rockchip64-current as mainline source
    • +
    • AR-15 - Drop Rockchip 4.19.y NEXT, current become 5.3.y
    • +
    • AR-16 - Rename RK3399 default to legacy
    • +
    • AR-17 - Rename Odroid XU4 next and default to legacy 4.14.y, add DEV 5.4.y
    • +
    • AR-18 - Add Odroid N2 current mainline
    • +
    • AR-19 - Move Odroid C1 to meson family
    • +
    • AR-20 - Rename mvebu64-default to mvebu64-legacy
    • +
    • AR-21 - Rename mvebu-default to mvebu-legacy
    • +
    • AR-22 - Rename mvebu-next to mvebu-current
    • +
    • AR-23 - Drop meson64 default and next, current becomes former DEV 5.3.y
    • +
    • AR-24 - Drop cubox family and move Cubox/Hummingboard boards under imx6
    • +
    • AR-26 - Adjust motd
    • +
    • AR-27 - Enabling distribution release status
    • +
    • AR-28 - Added new GCC compilers
    • +
    • AR-29 - Implementing Ubuntu Eoan
    • +
    • AR-30 - Add desktop packages per board or family
    • +
    • AR-31 - Remove (Ubuntu/Debian) distribution name from image filename
    • +
    • AR-32 - Move arch configs from configuration.sh to separate arm64 and armhf config files
    • +
    • AR-33 - Revision numbers for beta builds changed to day_in_the_year
    • +
    • AR-34 - Patches support linked patches
    • +
    • AR-35 - Break meson64 family into gxbb and gxl
    • +
    • AR-36 - Add Nanopineo2 Black
    • +
    • AR-38 - Upgrade option from old branches to new one via armbian-config
    • +
    • AR-41 - Show full timezone info
    • +
    • AR-43 - Merge Odroid N2 to meson64
    • +
    • AR-44 - Enable FORCE_BOOTSCRIPT_UPDATE for all builds
    • +
    • AR-57 - New kernel feature requested CONFIG_BLK_DEV_DRBD
    • +
    • AR-60 - Modified logrotate.service
    • +
    • AR-63 - Docker maintenance features
    • +
    +

    Bugs

    +
      +
    • AR-25 - Armbian resize stopped working in Ubuntu 19.10 or higher
    • +
    • AR-40 - When changing console layout it does not change
    • +
    • AR-51 - Prevent configuring locale
    • +
    • AR-52 - Broken desktop install
    • +
    • AR-54 - Upstream package name changed
    • +
    • AR-55 - Wireless driver remove patch for Odroid XU4 broke down
    • +
    • AR-56 - Missing CPU regulator
    • +
    • AR-58 - Troubles with wireless on Nanopi DUO & Opi Zero
    • +
    • AR-59 - Compressed files are getting back to /var/log
    • +
    • AR-62 - No HDMI sound on various meson64 boards
    • +
    • AR-64 - Docker require root
    • +
    • AR-68 - Broken Ethernet on Pine64+
    • +
    +

    Stories

    +
      +
    • AR-61 - Adding support for LOCAL_MIRROR
    • +
    • AR-65 - Moving configs under userpatches
    • +
    • AR-66 - Enable build system torrent download by default
    • +
    • AR-67 - Install Docker when we want to build under Docker
    • +
    • AR-69 - Use kernel command line instead of a patch
    • +
    • AR-70 - Enable Lima kernel driver on meson64
    • +
    • AR-73 - Enable PCI on Rockpi 4 and overlay for GEN2 speed
    • +
    +

    v5.98 (2019-10-09)

    +
      +
    • changed ntptime with chrony
    • +
    • fixed serial console on several hosts
    • +
    • added FriendlyARM ZeroPi
    • +
    • enabled gadgets on rockchip64
    • +
    • bumped RK3399 boards to latest kernel, recreate images and repository
    • +
    • merged odroidxu4 down to default since we only have one kernel
    • +
    • fixed Cubox images, move them to stock kernel
    • +
    • fixed low Synaptic search speed
    • +
    +

    Build script:

    +
      +
    • script configurations were migrated to userpatches
    • +
    • added option to create minimal images with around 500Mb in size BUILD_MINIMAL=”yes”
    • +
    • added initial support of MCIMX7SABRE board (CSC)
    • +
    • updates for xt-q8l-v10 (CSC)
    • +
    • Docker is installed automatically if one want use it (Debian based build host only)
    • +
    • refactor build all images scripting that images can be build in full parallel mode
    • +
    • added one file for storing which combinations shell be made for each board
    • +
    • replaced Etcher with dd + verify for directly burning images when done
    • +
    • cleaned initial config and remove confusing advanced options out
    • +
    +

    v5.92 (2019-08-02)

    +
      +
    • updated sunxi NEXT (4.19.63) and DEV (5.2.5) kernels
    • +
    • updated htop application to show cpu speed and temperature (buster / disco)
    • +
    +

    v5.91 (2019-07-31)

    +
      +
    • created new images for Helios4 and Clearfog Pro/Base
    • +
    • moved mvebu DEFAULT, NEXT and DEV branch to next kernel (LTS) and U-boot version
    • +
    • fixed armada_thermal sensor reading, adjusted Helios4 fancontrol configuration
    • +
    • fixed ODT on data signals of DDR RAM for Armada A388 SOMs
    • +
    • recreated Armbian Buster images due to a bug in Network manager which in some cases failed to initiate network connection
    • +
    +

    Armbian-config:

    +
      +
    • added Emby installation
    • +
    • updated Plex install to use official repo
    • +
    • added netmask-to-CIDR function for manual IP configuration
    • +
    +

    v5.90 (2019-07-07)

    +
      +
    • added Armbian Buster images for all boards
    • +
    • added Macchiatobin Doubleshot CSS target and images
    • +
    • added images with test kernel v5.1.y for: Orangepi3, Lite2, One+, PineH64, Odroid C1, Teres, Pinebook
    • +
    • added wireless drivers for 88x2bu
    • +
    • added eMMC support for Nanopi K2 (booting from doesn’t work yet)
    • +
    • added dual w1 overlay for meson64 family
    • +
    • updated wireless drivers for Realtek 8811, 8812, 8814 and 8821
    • +
    • updated wireless drivers for rtl8188eus & rtl8188eu & rtl8188etv
    • +
    • added latest Wireguard driver
    • +
    • enable eMMC on Orangepi Win Plus
    • +
    • enable Bluetooth on Tinkerboard, Nanopi4, Rockpi 4 CLI images
    • +
    • improved ALSA config on Tinkerboard
    • +
    • fixed Bluetooth on Nanopi M4/Neo4/T4 and Rockpi4
    • +
    • fixed wireless drivers on OPi3 & Lite2
    • +
    • fixed temperature readout on Allwinner H5 boards
    • +
    • fixed SPI related bug on Allwinner 5.1.y kernel
    • +
    • fixed HDMI output and bump kernel to 5.1.y on imx6 boards
    • +
    • fixed eMMC install, add rootdev= to armbianEnv if missing
    • +
    • fixed A10/A20 SATA write speed
    • +
    • set default build target from Debian Stretch to Buster for all boards
    • +
    • changed CPU clock back to 1.5/1.8Ghz defaults on boards with RK3399 to minimise thermal throttling
    • +
    • changed motd console welcome text to: “Welcome to Debian Stretch with Armbian Linux 5.1.6-sunxi”
    • +
    • changed display manager to lightdm by default and remove nodm completely
    • +
    • changed u-boot for A64 to upstream sources
    • +
    • changed RK3399 to U-boot 2019.04
    • +
    • added URL to the build script and commit hash to /etc/armbian-release file
    • +
    • added synaptic package manager and on-board keyboard to the desktop base
    • +
    • added “logout” to the panel/menu
    • +
    • added normal users to additional groups: disk tty users games
    • +
    • updated all kernels with upstream
    • +
    • updated ATF and bootloader on Espressobin, supporting all versions
    • +
    +

    Build script:

    +
      +
    • added mirrors for speed-up building in China mainland
    • +
    • added support for download compilers and rootfs cache via torrent network
    • +
    • added new output image compression option (xz)
    • +
    • enabled Debian Buster and Ubuntu Disco (unsupported) targets
    • +
    • few Docker building improvements, caching image
    • +
    • replace curl with aria2
    • +
    • Linaro compilers update to 2019.02
    • +
    +

    Armbian-config:

    +
      +
    • added Gimp installation
    • +
    • added enable/disable Avahi
    • +
    • updated OMV installer, OMV5 preparations
    • +
    • enable screen resolution changer for Odroid N2
    • +
    • enable CPU speed and governor adjustment
    • +
    +

    v5.87 (2019-05-26)

    +
      +
    • added support for Odroid N2, Nanopi R1, Nanopi Duo2
    • +
    • enabled nightly images for Orangepi3, One+, Lite2, PineH64, Rock64pro, RockPi4b
    • +
    • enabled nigtly Buster and Disco images for Le Potato
    • +
    • recompiled all images and pushed update where updates are known to work (sunxi, sunxi64, meson64, …)
    • +
    • improved SATA write speed on A20 chips for up to 300%
    • +
    • fixed thermal throtling for H5 devices
    • +
    • mainline u-boot moved 2019.04
    • +
    • most development kernels moved to 5.1.y
    • +
    • added separate DT for espressobinv7, updated boot loader
    • +
    • enable WoL for eth0 on Helios4
    • +
    +

    Build script:

    +
      +
    • added Debian Buster and Ubuntu Disco (WIP)
    • +
    • improved building under Docker. Source code is not copied to docker image, caching image
    • +
    • Linaro compilers update to 2019.02
    • +
    • fixed incomplete cleaning of the source code
    • +
    +

    Armbian-config:

    +
      +
    • fixed kernel changing
    • +
    • fixed sources download
    • +
    • fixed Hass.IO and TVheadend install
    • +
    • added menu driven CPU frequency/governor adjustement
    • +
    • improved two-factor authentication
    • +
    • added meson64 and rockchip to overlay/hardware configuration
    • +
    • improved hostapd management
    • +
    +

    Infrastructure:

    +
      +
    • main download server has been hooked to 10GbE connection.
    • +
    • added web/http seeds to torrent download. Torrent download could/should fully utilize your download capacity.
    • +
    • major forum upgrade (v4.4.3)
    • +
    • added another IPV6 capable EU mirror https://mirrors.dotsrc.org
    • +
    +

    v5.76 (2019-02-11)

    +
      +
    • remove Exagear Desktop
    • +
    +

    v5.75 (2019-02-10)

    +
      +
    • added updated driver for Realtek 8811, 8812, 8814 and 8821 chipsets
    • +
    • added Wireguard support to remaining kernels (except lower than 3.10)
    • +
    • images rebuild with latest upstream sources, mainline u-boot was bumped to 2018.11
    • +
    +

    v5.74 (2019-01-31)

    +
      +
    • fixing systemd related bug found in sunxi legacy 3.4.y kernels
    • +
    +

    v5.73 (2019-01-29)

    +
      +
    • much faster armbian-install operations. Thanks to @dedalodaelus
    • +
    • added support for @wireguard on all kernels higher than 3.10.y
    • +
    • fixed drivers for popular DVB tuner S960 (all kernels)
    • +
    • fixed bug in wireless drivers on Cubietruck, BananpiPRO, Bananapi+
    • +
    • fixed AP mode on Orangepi PC+, Prime, One, .. when using kernel 4.19.y
    • +
    • added prolific USB-to-USB bridges in mvebu-next/dev
    • +
    • added nftables masquerade in mvebu64-next
    • +
    • added MD raid support for SUNXI64
    • +
    • upgrade bugfix for Helios4
    • +
    • updated hostapd to 2.7
    • +
    • fixed 1512MHz OPP on Renegade
    • +
    • fixed DRM crashing for rockchip64
    • +
    • mainline u-boot bumped to 2018.11 (update goes manually from armbian-install utility)
    • +
    • added testing images for Orangepi RK3399 and Radxa Rockpi 4B
    • +
    +

    v5.72 (2019-01-16)

    +
      +
    • added additional repository mirror (updated armbian-config)
    • +
    • fixed Tinkerboard DTB in repository and images rebuild
    • +
    +

    v5.71 (2019-01-16)

    +
      +
    • updated images for Odroid C2, Lepotato and Nanopik2-S905 due to this bug
    • +
    +

    v5.70 (2019-01-12)

    +
      +
    • sunxi-next and sunxi64-next were moved from 4.14.y to 4.19.y (remake of all AW images)
    • +
    • better DVFS on H3/H5/A64, enabled higher cpu speed.
    • +
    • added overlay support for Tinkerboard/rockchip next and kernel upped to 4.19.y
    • +
    • updated next kernel for Odroid XU4 to 4.19.y
    • +
    • updated next kernel for Odroid C2, Lepotato and Nanopik2-S905 to 4.19.y with overlay support
    • +
    • fixed poweroff on H5
    • +
    • H5/A64 lost experimental status,
    • +
    • upgraded images and upstream/bugfix kernel upgrade for Rock64, Renegade,
    • +
    • u-boot update is moved from automated to manual (armbian-config) to minimize boot related troubles
    • +
    • added two repository mirrors: China and France (armbian-config -> Personal -> Mirror)
    • +
    • changed switching to alternative kernels from armbian-config. It is possible to select a direct version and it only replaces kernel (safer)
    • +
    • first official build for Olimex Teres
    • +
    • mainline kernel builds for: Pine64, Pine64so, Olinuxino A64, OrangepiWin
    • +
    • added more download variants for Rock64, Renegade, Tritium H3&H5
    • +
    • updated images for Z28PRO, Bananapi PRO, Espressobin, Olimex Micro, Lime, Udoo, Bananapi M2, Bananapi M2U,
    • +
    +

    v5.68 (2018-12-30)

    +
      +
    • updated Espressobin images, kernel updated to 4.19.y
    • +
    +

    v5.67 (2018-11-26)

    +
      +
    • updated Helios4 images
    • +
    • added experimental mainline kernel images for Pinebook and Pinebook 1080p
    • +
    +

    v5.67 (2018-11-12)

    +
      +
    • updated images for Bananapi R2 with eMMC install support.
    • +
    +

    v5.66 (2018-11-08)

    +
      +
    • added Mediatek MT7623 family.
    • +
    • added images for Bananapi R2 with kernel 4.19.y without official support.
    • +
    +

    v5.66 (2018-11-07)

    +
      +
    • removing Odroid C2 official support, drop its default 3.16.y kernel from build engine and merge with the meson64 family.
    • +
    • attach meson64 dev to 4.19.y
    • +
    • drop Udoo Neo completly, drop Udoo Quad default and dev kernel.
    • +
    • Odroid XU4: drop kernel 3.10.y, default branch is upgraded to offical 4.14.y, next becomes vanilla 4.19.y
    • +
    +

    v5.65 (2018-11-06)

    +
      +
    • Cubox-i/Hummigboard: drop kernel 3.14.y and move 4.14.y to default, next becomes 4.19.y, dev 4.19.y with a mainline u-boot
    • +
    +

    v5.64 (2018-10-09)

    +
      +
    • updated images and packages for Helios4.
    • +
    • added images for Nanopi Neo4.
    • +
    +

    v5.63 (2018-10-08)

    +
      +
    • updated images for Helios4 with SPI booting support.
    • +
    • updated armbian-config. Added advanced ZSH shell install with most used plugins and tmux.
    • +
    +

    v5.62 (2018-10-01)

    +
      +
    • updated armbian-config
    • +
    +

    v5.61 (2018-09-26)

    +
      +
    • updated armbian-config,
    • +
    • fixed Chromium on Debian builds with a workaround. We are overwriting package with last known working one. It will show some error on startup which is safe to ignore. This workaround will fade out with Chromium upstream update.
    • +
    +

    v5.60 (2018-09-19)

    +

    Changes overview:

    +

    General:

    +
      +
    • Ubuntu Xenial was replaced with Bionic unless kernel was too old for the change,
    • +
    • Debian Jessie becomes EOL and its building is not maintained anymore while you will still receive kernel updates,
    • +
    • Emergency swap file creation is disabled by default since we use compressed memory (ZRAM) as an alternative,
    • +
    • vm.swappiness has been changed from 0 to 100 (if you run databases on your board you might want to revert this change in /etc/sysctl.conf),
    • +
    • RAM logging also uses ZRAM now and rotates logs automagically,
    • +
    • all images were rebuilt, except boards for which support ended,
    • +
    • significantly lighter - browser only - desktop images (< 1.5G),
    • +
    • fixed hanging on headers installation,
    • +
    • install boot script (BSP package) if not present. This fixes upgrade or kernel switching problems,
    • +
    • Proper bind mount directory when installing to SATA/USB and booting from SD,
    • +
    • update for wireless drivers 8812/11/14AU, 8188EU and AUFS,
    • +
    • Bugfix when a temperature is not present or readings are invalid,
    • +
    • Also showing bridge IP addresses in MOTD,
    • +
    • storing package list compressed - saves 50-70Mb,
    • +
    • enlarging automated apt-get update and purge intervals,
    • +
    • smaller overhead for CLI images,
    • +
    • improved alternative kernel switching,
    • +
    • stop setting Google’s DNS server as default for privacy reasons.
    • +
    +

    Family:

    +
      +
    • sunxi and sunxi64, u-boot was bumped to 2018.05, NEXT branch was updated to the latest 4.14.y, DEV is attached to 4.18.y + fixed overlay support,
    • +
    • mvebu64, default BSP kernel was upgraded to 4.14.y, NEXT to 4.18.y,
    • +
    • odroidc1, experimental NEXT kernel branch was attached to 4.18.y,
    • +
    • odroidc2 kernel was merged with meson64 on the source level,
    • +
    • meson64 u-boot was pushed to 2018.05, a default was updated to the latest 4.14.y, NEXT to 4.18.y,
    • +
    • rk3288, u-boot was pushed to 2018.05, legacy kernel cleaned and fixed after upstream troubles, NEXT branch was updated to the latest 4.14.y,
    • +
    • rockchip64, rk3399 was split into rk3399 for Friendly ARM boards and rockchip64 for Rock64 and RockPro, Ayufan repository. Merging is postponed for the future,
    • +
    • s5p6818 family support added NEXT branch was updated to the latest 4.14.y,
    • +
    • mvebu, NEXT branch was updated to latest 4.14.y, DEV attached to 4.18.y,
    • +
    • fixed randomly failing X server on imx6 family,
    • +
    +

    Board:

    +
      +
    • added WIP support for Firefly RK3399, Lime A64, Renegade, Rockpro64, Olimex Teres
    • +
    • added experimental images for Bananapi M3 and Cubietruck+,
    • +
    • adeed support for: Tinkerboard S, Rock64, Orangepi Zero Plus, Nanopi Neo Core2, Nanopi M4,
    • +
    • added NEO 1.1 regulator overlay,
    • +
    • added Helios4 device tree with FAN control for modern kernel,
    • +
    • enabled SPI access on Espressobin,
    • +
    • updated SPI boot firmware on Espressobin (18.09.1) with many fixes and support for booting from USB, SATA, eMMC or SD,
    • +
    • added Tinkerboard S DC-IN voltage to armbianmonitor,
    • +
    • fixed network interface initialization,
    • +
    • fixed clock drift on Bananapi boards,
    • +
    • enabled concurrent AP/STA mode on Tinkerboard,
    • +
    • improved support for NanoPi Fire 3 (added SPU1705, DVFS, thermal tables, etc.),
    • +
    • fixed network crashing on high load. Affected: Odroid C1/C2, Le Potato kernel 4.18.y,
    • +
    • fixed wireless, eMMC and Bluetooth on (unsupported) Z28 PRO and changed boot order,
    • +
    • fixed eMMC install on NanoPC T3+ and Docker dependencies on Fire3, M3, NanoPC T3+,
    • +
    • added eMMC and DVFS support on Espressobin mainline kernel,
    • +
    • ported Tinkerboard UMS to modern u-boot,
    • +
    • enabled 1392 MHz cpufreq OPP on all RK3328 devices,
    • +
    • enabled 1992/1512MHz cpufreq OPP on all RK3399 devices,
    • +
    • added eMMC to OlinuXino A64 kernel and u-boot,
    • +
    • added Sunvell R69 CSC target,
    • +
    • OrangepiWin: fixed BT,
    • +
    • fixed ethernet on (unsupported) Bananapi M64.
    • +
    +

    Build script:

    +
      +
    • changed recommended build host to Bionic, Xenial still supported for everything except building Bionic images,
    • +
    • added support for burning image directly to SD card when your build is done by using Etcher for CLI,
    • +
    • added support for making LUKS encrypted root images, parameters: CRYPTROOT_ENABLE=yes, CRYPTROOT_PASSPHRASE=unlockpass,
    • +
    • fixed building under Docker, bumped to Bionic host,
    • +
    • added building Bionic and block building it for images with too old kernels,
    • +
    • added multibranch support (LIB_TAG).
    • +
    +

    Infrastructure:

    +
      +
    • build machine main SSD and memory upgrade, switched from bare metal Ubuntu Xenial to fully optimsed Debian KVM server, free build capacity is avaliable for any armbian related activity upon request,
    • +
    • download server drive capacity and download speed upgrade, IPV6,
    • +
    • geo load balancing for repository and download server is under testing,
    • +
    • improved repository management. Possibility to add packages via Github,
    • +
    • introducing new internal parameter, example: BUILD_ALL=”yes” REBUILD_IMAGES=”bananapi,udoo,rock64” to specify which images need rebuilding,
    • +
    • main torrent server cleanup, removed deprecated images,
    • +
    • creating report https://beta.armbian.com/buildlogs/report.html when building all kernels. Prepared to include simple per board testing report where exists armbian/testings.
    • +
    +

    Known bugs:

    +
      +
    • modern kernel support on A64 boards is mainly broken.
    • +
    +

    v5.59 (2018-08-18)

    +
      +
    • rebuilt images for Espressobin with kernel 4.18.y, Nanopc T4
    • +
    +

    v5.58 (2018-08-13)

    +
      +
    • rebuilt images for Bananapi, Bananapi Pro, Bananapi+, Odroid C2, Odroid XU4
    • +
    • updated repository for Odroid C2/XU4, changed NEXT from 4.9.y to 4.14.y
    • +
    +

    v5.58 (2018-08-13)

    +
      +
    • rebuilt images for Bananapi, Bananapi Pro, Bananapi+
    • +
    +

    v5.57 (2018-08-11)

    +
      +
    • added Bionic desktop and Stretch CLI images for RK3399 powered Nanopc T4
    • +
    +

    v5.56 (2018-08-10)

    +
      +
    • rebuilt images for Pinebook. Added Bionic build
    • +
    +

    v5.55 (2018-08-09)

    +
      +
    • rebuilt images for Orangepi One+, Orangepi Lite 2 and Pine H64. Enabled USB3, network, THS, DVFS, higher frequencies, HDMI on 4.18.y DEV branch images.
    • +
    +

    v5.55 (2018-08-03)

    +
      +
    • added Stretch and Bionic mainline kernel images for Odroid C1 (testing),
    • +
    • rebuilt images for Bananapi M3 (fixed ethernet)
    • +
    +

    v5.54 (2018-07-25)

    +
      +
    • updated images for Odroid C2, Nanopi M3, Nanopi Fire 3 and NanoPC T3+, Espressobin, Cubox-i/HB and Le potato
    • +
    • added preview images without end user support for Bananapi M3,Cubietruck+ and Bananapi M2 Berry.
    • +
    +

    v5.53 (2018-07-23)

    +
      +
    • Z28PRO images updated. Fixed wireless and Bluetooth
    • +
    • FriendlyARM Nanopi K2 S905 images updated. Fixed ethernet problems.
    • +
    • FriendlyARM Nanopi K1+ images updated. Fixed HDMI out and wireless
    • +
    +

    v5.51 (2018-07-04)

    +
      +
    • Helios4 Stretch and Bionic images update
    • +
    +

    v5.50 (2018-06-28)

    +
      +
    • Espressobin images rebuild and repository update, default 4.4.138, next 4.17.3, dev 4.18.RC, hardware crypto support in 4.17.y, zram and zswap
    • +
    • Odroid C2 bugfix update
    • +
    +

    v5.49 (2018-06-28)

    +
      +
    • Amlogic Meson64 family (Odroid C2, Lepotato and FriendlyARM K2 S905) were merged into one kernel. Default images comes with kernel 4.14.52, next with 4.17.3 and DEV with 4.18.RC, updated boot scripts, implemented latest kernel bug fixes
    • +
    • updated kernels, desktop packages and armbian config on the stable repository (apt update & upgrade)
    • +
    +

    v5.48 (2018-06-26)

    +
      +
    • added nightly images for Odroid C2 with 4.16.y (NEXT) and 4.18.y (DEV) and hopefully fixed ethernet driver
    • +
    +

    v5.47 (2018-06-22)

    +
      +
    • Odroid C2 images rebuild. Legacy kernel was upgraded to 3.16.57, next to 4.14.51, u-boot to 2018.05
    • +
    • Added Tritium H5
    • +
    +

    v5.46 (2018-06-20)

    +
      +
    • Added Olimex Teres nightly builds
    • +
    • Added FriendlyARM Nanopi K1 plus
    • +
    +

    v5.46 (2018-06-06)

    +
      +
    • Added Orange Pi Lite 2 and One plus nightly builds
    • +
    +

    v5.45 (2018-05-23)

    +
      +
    • Orangepi Zero+ images rebuild
    • +
    +

    v5.44 (2018-05-10)

    +
      +
    • Espressobin images were rebuilt and moved under stable. Kernel 4.14.40, Stretch, Xenial and Bionic. Fixed bootloader, ath10 wireless card support
    • +
    • added initial Bionic storage to the main apt repository
    • +
    • Cubox-i / Hummingboard bugfix update to 4.16.y and images rebuild
    • +
    • Odroid C2 images rebuild
    • +
    +

    v5.41 (2018-02-10)

    +
      +
    • fixed LED driver on Helios4
    • +
    • bugfix update on sunxi/sunxi64 kernel. Updated to 4.14.18
    • +
    • kernel update for MVEBU next (4.14.18 and default 4.4.115) for Clearfog and Helios4. Upstream fixes,AUFS and Realtek 881yAU drivers update
    • +
    +

    v5.40 (2018-02-05)

    +
      +
    • fixed eMMC support on Odroid C2 NEXT, kernel 4.14.y
    • +
    • updated PWM driver on Helios4
    • +
    • kernel update for MVEBU next (Clearfog, Helios4)
    • +
    +

    v5.38 (2018-01-29)

    +
      +
    • updated all images
    • +
    • added H3/H5 testing images with kernel 4.14.y
    • +
    • added Nanopi M3/T3+/Fire testing image
    • +
    • fixed Bluetooth on Orangepi Win
    • +
    • main repository update with recent kernel on all NEXT builds
    • +
    +

    v5.37 (2018-01-23)

    +
      +
    • bugfix release
    • +
    • armbianmonitor -u fix
    • +
    • setting cronjob permissions
    • +
    • replace broken u-boot packages on A20 boards
    • +
    • updated utilities: hostapd, sunxi-tools, armbian-config
    • +
    • updated images: Bananapi, PRO, M2, BeelinkX2, Clearfog,Cubieboard2, Cubietruck, Cubox-i/HB, Espressobin, Helios4
    • +
    +

    v5.36 (2017-12-03)

    + +

    v5.35 (2017-11-25)

    +
      +
    • mainline kernel updated to 4.13.y
    • +
    • mainline u-boot updated to v2017.09
    • +
    • added new sunxi Device Tree overlays, fixed and improved old overlays
    • +
    • Micro-USB g_serial console is enabled by default on most small Allwiner based boards
    • +
    • Olimex Lime2 and Micro: merging eMMC and normal versions
    • +
    • Odroid C2: next and dev branches migrated to mainline u-boot
    • +
    • Odroid XU4: added dev branch, next branch migrated to mainline u-boot
    • +
    • Clearfog: added dev branch with mainline u-boot
    • +
    • added supports for 7” RPi display to Tinkerboard with legacy kernel
    • +
    • All mainline kernels: added Realtek 8811AU/8812AU/8814AU USB wireless driver with monitor mode and frame injection
    • +
    • All boards: added kernel source packages to the repository (Package names linux-source-${BRANCH}-${LINUXFAMILY}, i.e. linux-source-sunxi-next)
    • +
    • Kernel headers are no longer installed by default to new images
    • +
    • Additional out of tree drivers and USB Redirector are no longer installed by default to new images
    • +
    • Switching from emergency swap to zram on new Ubuntu Xenial images
    • +
    • New hardware support (stable/supported images): NanoPi Duo, Orange Pi R1, Pinebook
    • +
    • New hardware support (experimental): Le Potato, NanoPi NEO 2, Orange Pi Zero Plus, Orange Pi Zero Plus 2 (H5)
    • +
    • sunxi mainline u-boot: reenabled USB keyboard support and disabled stopping the boot sequence with any key - autoboot now can be aborted with
    • +
    +

    Desktop images:

    +
      +
    • xterm was replaced with full featured xfce terminal,
    • +
    • added memory profile caching for Chromium,
    • +
    • added OpenVPN connector,
    • +
    • shortcuts to armbian-config, support and donate were moved to menu,
    • +
    • default icon theme was changed to lighter one (Numix),
    • +
    • fixed login greeter theme,
    • +
    • changed wallpaper.
    • +
    • changed CMA handling on Allwinner legacy kernels
    • +
    +

    armbian-config:

    +
      +
    • was splitted from board support packages to a new package armbian-config
    • +
    • managing board hardware configurations, hotspot, Bluetooth, SSH server
    • +
    • freezing/unfreezing kernel upgrade
    • +
    • switching between stable and beta builds,
    • +
    • switching between alternative kernels,
    • +
    • installing/uninstalling kernel headers,
    • +
    • changing timezone, locales, hostname,
    • +
    • running diagnostic tools,
    • +
    • enabling/disabling RDP server,
    • +
    • 3rd party software installer: Samba, OMV, Pi hole, Transmission, …
    • +
    +

    Build script:

    +
      +
    • added Debian Stretch
    • +
    • most tweaks moved from inline files to separate files in board support package
    • +
    • firmware blobs moved to a separate repository
    • +
    • disabled distcc in extra software compilation process due to toolchain compatibility issues
    • +
    + + +

    v5.34 (2017-10-18)

    + +

    v5.33 (2017-09-24)

    +
      +
    • Odroid XU4/HC1 images were rebuilt.
    • +
    +

    v5.33 (2017-09-21)

    +
      +
    • Tinkerboard and MiQi images were rebuilt. Rockchip legacy kernel was updated to 4.4.88 and mainline (NEXT) to 4.13.3.
    • +
    +

    v5.32 (2017-06-23)

    + +

    v5.31 (2017-06-15)

    + +

    End of support notice

    +

    Following boards are no longer receiving support and updates since this version:

    +
      +
    • Cubieboard (Allwinner A10) - not enough hardware samples to maintain support
    • +
    • Lamobo R1 (Allwinner A20) - hardware design flaws, poor software support for the onboard switch
    • +
    • Olimex Lime A10
    • +
    +

    v5.30 (2017-06-14)

    +
      +
    • mainline kernel updated to 4.11
    • +
    • mainline u-boot updated to v2017.05
    • +
    • Firefox was replaced with Chromium (desktop images)
    • +
    • sunxi mainline configuration: added Device Tree overlays support (new images only)
    • +
    • sunxi mainline configuration: added armbian-add-overlay helper for compiling and activating DT overlays (new images only)
    • +
    • log2ram: fixed saving /var/log contents on shutdown
    • +
    • new hardware support (stable/supported images): Xunlong Orange Pi Zero Plus 2 (H3), ASUS TinkerBoard, MiQi
    • +
    • reworked package updates MOTD script to speed up the login process
    • +
    • added config file /etc/default/armbian-motd for disabling MOTD components
    • +
    • added armbian-config dialog-based configuration program (WIP)
    • +
    • Banana Pi M2: fixed HDMI video output
    • +
    • Clearfog: adjusted temperature readout
    • +
    • i.MX6 mainline: enabled support for HDMI audio and PCIe bus
    • +
    +

    End of support notice

    +

    Following boards are no longer receiving support and updates since this version:

    +
      +
    • Orange Pi (Allwinner A20) - no hardware samples, out of stock
    • +
    • Orange Pi Mini (Allwinner A20) - no hardware samples, out of stock
    • +
    • LeMaker Guitar (Actions S500)
    • +
    • Roseapple Pi (Actions S500)
    • +
    +

    v5.26, v5.27 (2017-02-24)

    +
      +
    • security update for most kernels (packages only)
    • +
    • fixes for hostapd configuration
    • +
    +

    v5.25 (2017-02-02)

    +
      +
    • armbian-install expanded functionality: you can partition destination and choose file-system type: ext2, ext3, ext4 and BTRFS (BTRFS requires kernel 4.4+)
    • +
    • added new boards: Clearfog Base, Lime2 eMMC, Lime A33, NanoPi M1+, OrangePi Zero, OrangePi PC2 (mainline only, experimental)
    • +
    • new default kernel for Clearfog(s), changed kernel family to “mvebu” to avoid conflicts
    • +
    • disabled wireless power management by default to improve performance with certain drivers
    • +
    • added wireless drivers to mainline kernels: OrangePi Zero, Neo Air
    • +
    • implemented initrd loading support for all boards
    • +
    • moved all images to single ext4 partition scheme
    • +
    • changed default wallpaper, startup icon, shadows to windows on desktop builds
    • +
    • Firefox web cache moved to memory
    • +
    • added g_serial driver to boards without a network connector, working on both kernel (Opi Zero,Opi Lite,FA Neo Air)
    • +
    • added “Software boutique” application installer on desktop builds (currently not working properly on arm64)
    • +
    • added per board patching option
    • +
    • added u-boot video driver and boot logo to H3 based boards
    • +
    • added simplefb video driver (HDMI only) to mainline H3 kernel
    • +
    • updated MALI driver on H3 platform, fixed problems on 2GB boards
    • +
    • changed Ethernet switch driver on Lamobo R1 to DSA based one (mainline kernel)
    • +
    • fixed soft cursor (CLI) for H3 legacy and Odroid C2
    • +
    • expand and adjust multiple kernel configurations based on user requests
    • +
    • adjusted sunxi boot script to support booting in SPI flash + USB storage scenario (w/o the SD card)
    • +
    • dropped support for Debian Wheezy and Ubuntu Trusty releases
    • +
    • sunxi mainline kernel was updated to 4.9.x, some dev kernels to 4.10
    • +
    • added log2ram (Ramlog alternative) to default installation
    • +
    • changed first run logic, disabled forced automatic reboot
    • +
    • changed new user account creation logic, disabled forced reboot on user creation failure
    • +
    +

    v5.24

    +
      +
    • this version is not released, it was used for the nightly or user-built images
    • +
    +

    v5.23 (2016-10-23)

    +
      +
    • fixed bug in armbian-install
    • +
    • fixed u-boot update bug on Allwinner platform
    • +
    +

    Known problems:

    +
      +
    • Lamobo R1 fails to boot upon upgrade
    • +
    +

    v5.22 (2016-10-22)

    +
      +
    • fixed eMMC install on Odroid C2
    • +
    • firmware package was splitted into minimal (default) and full versions
    • +
    • patched Dirty COW exploit on all kernels
    • +
    • added Odroid XU4 mainline kernel image
    • +
    • added Olimex A33 mainline kernel image
    • +
    • added Overlay FS for Cubox, Udoo and Udoo Neo
    • +
    • booting problems fixed on more boards
    • +
    • updated wireless driver on M2+ (dhd)
    • +
    • updated driver for OV5640 on sun8i default kernel
    • +
    • sunxi-next kernel version updated to 4.8.4
    • +
    • BananaPi M1+ now uses upstream DTB file sun7i-a20-bananapi-m1-plus.dtb, boot script adjusting may be required for existing images
    • +
    +

    Desktop images:

    +
      +
    • prebuilt mpv and FFmpeg were removed in favor of providing only configuration files
    • +
    • fixed an issue with video brightness on A10/A20 based boards
    • +
    +

    Build script:

    +
      +
    • DEBUG_MODE was renamed to CREATE_PATCHES
    • +
    • GLshim was moved to a private directory, it can be activated for selected applications by changing LD_LIBRARY_PATH
    • +
    +

    Known problems:

    +
      +
    • eMMC install fails (will be fixed in bugfix update)
    • +
    • H3 development kernel (4.8.4) update fails to boot
    • +
    • C2 upgrade hangs on compiling headers (Jessie)
    • +
    +

    v5.20 (2016-09-16)

    +
      +
    • added FriendlyARM Neo legacy and mainline images (experimental)
    • +
    • added Orange Pi PC+ mainline kernel (experimental)
    • +
    • added Pine64 / Pine64+ images with legacy kernel
    • +
    • added UUID support for NAND/SATA/USB installer
    • +
    • added desktop images for Cubox(s) / Hummingboard(s) with mainline kernel
    • +
    • enabled MIDI sequencer and snd-rawmidi-seq in H3 legacy kernel
    • +
    • added H3 consumption tool to control board consumtion level on legacy kernel
    • +
    • fixed and enabled Bluetooth on Cubietruck and Cubox(s) / Hummigboard(s) desktop, both kernels
    • +
    • masked p2p0 wifi direct device on Bluetooth legacy kernel
    • +
    • Odroid C1/C2 upgrade fail fixed
    • +
    • wireless enabled by default on Banana Pi PRO
    • +
    • added new screen resolutions to H3 boards with legacy kernel
    • +
    • DeviceTree Overlay ConfigFS interface for H3 mainline kernel
    • +
    • update of mainline u-boot to 2016.09 should fix boot failures on H3 boards with eMMC
    • +
    • disabled USB keyboard support in mainline u-boot should fix boot failures with connected USB devices
    • +
    +

    Desktop images:

    +
      +
    • WICD was replaced with NetworkManager
    • +
    • ALSA was replaced with PulseAudio
    • +
    • sunxi boards: GLshim was added to desktop images with Mali support (except for Orange Pi Plus and Orange Pi Plus 2e)
    • +
    • sunxi boards: prebuilt mpv now supports OSD and subtitles, activated by setting environment variable VDPAU_OSD=1
    • +
    +

    Build script:

    +
      +
    • complete desktop building rework - now packages are built from sources
    • +
    • added Lime 2 eMMC as build target (WIP)
    • +
    • added Pine64 / Pine64+ mainline (dev) target (experimental)
    • +
    • added FriendlyArm Neo as build target
    • +
    • fixed MT7601 wifi driver building
    • +
    • github download rework
    • +
    • external toolchain rework
    • +
    +

    Added additional packages, not installed by default:

    +
      +
    • hostapd-realtek: replacement for hostapd with support for several Realtek Wi-Fi adapters
    • +
    • fswebcam-gc2035: replacement for fswebcam with support for GC2035 camera driver for H3 based boards
    • +
    • guvcview: replacement for stock guvcview with support for H3-based Orange Pi CMOS cameras
    • +
    +

    Known problems:

    +
      +
    • Mali OpenGL ES does not work on H3 boards with 2GB RAM (Orange Pi Plus 2, Orange Pi Plus 2e)
    • +
    • Hardware video decoding on A10/A20 based boards produces dark video
    • +
    • Some applications that depend on livav libraries (i.e. minidlna) may not work on Jessie images
    • +
    +

    v5.17 (2016-07-07)

    +
      +
    • bugfix release on some boards.
    • +
    +

    v5.16 (2016-07-05)

    +
      +
    • bugfix release. In 5.15 we accidentaly overwrote default network settings. Check /etc/network/interfaces if you use advanced network settings or fixed ip.
    • +
    • small changes.
    • +
    +

    v5.15 (2016-07-01)

    +
      +
    • Added improved camera driver for Xunlong’s cheap 2MP GC2035 camera
    • +
    • Improved throttling/DRAM settings for the new 3 overheating H3 devices (BPi M2+, NanoPi M1, Beelink X2)
    • +
    • Added official support for Beelink X2, NanoPi M1, Banana Pi M2+
    • +
    • Improved console output (serial + display)
    • +
    • Finally got rid of (broken) board auto detection. We do not ship any more one image for several devices that tries to detect/fix things on 1st boot but provide one dedicated image per board (Plus and Plus 2 and both NanoPi M1 variants being handled as the same device since only size of DRAM/eMMC differs)
    • +
    • Tried to improve user experience with better/unified led handling (light directly after boot, communicate booting states through blinking)
    • +
    • Improve partitioning and filesystem resize on 1st boot making it easier to clone every installation media afterwards
    • +
    • fully support installation on eMMC on all H3 devices (u-boot and armbian-install.sh fixes)
    • +
    • Improved performance/thermal/throttling behaviour on all H3 boards (especially newer Oranges)
    • +
    • Prevent HDMI screen artefacts (disabling interfering TV Out by default)
    • +
    • Enhanced 8189ETV driver for older Oranges
    • +
    • Added support for OPi Lite, PC Plus and Plus 2E including new 8189FTV Wi-Fi (client, AP and monitoring mode, added fix for random MAC address)
    • +
    • Added in-kernel corekeeper patch (bringing back killed CPU cores after heavy overheating situations when thermal situation is ok again)
    • +
    • Added TV Out patch for Orange Pi PC
    • +
    • Further improve driver compilation due to improved kernel headers scripts compilation
    • +
    • Initrd support
    • +
    • increased kernel version to 3.4.112
    • +
    • Exchanged whole kernel source tree to newer BSP variant, cleaned up sources, rebased all +100 patches (fixed display issues and kswapd bug, new and more performant GPU driver, increase Mali400MP2 clock to 600MHz)
    • +
    • Added RTL2832U drivers to kernel (DVB-T)
    • +
    • Fixed Docker on Odroid XU4
    • +
    • Added overlay fs to Clearfog and Odroid XU4
    • +
    • Many minor fixes
    • +
    +

    v5.14 (2016-06-14)

    +
      +
    • all images rebuilt, most of them were manually tested
    • +
    • added Beelink X2 image
    • +
    • Cubox / Hummingboard kernel upgrade to 3.14.72 and 4.6.2
    • +
    • Trusty was replaced with Xenial
    • +
    +

    v5.12 (2016-05-31)

    +
      +
    • updated C1 images
    • +
    • added wifi driver for new Oranges (modprobe 8189fs)
    • +
    • added Orange Pi Lite, PC Plus and Plus 2E images
    • +
    +

    v5.11 (2016-05-24)

    +
      +
    • Various bug fixes
    • +
    • new working images for Actions Semi S500 boards
    • +
    +

    v5.10 (2016-05-01)

    +

    Images:

    +
      +
    • all 3.10+ kernels are Docker ready
    • +
    • all A10/A20/H3 comes with HW accelerated video playback in desktop build
    • +
    • fixed root exploit on H3 boards
    • +
    • fixed kswapd 100% bug on H3 boards
    • +
    • fixed SPDIF / I2S audio driver in legacy kernel
    • +
    • fixed Udoo Neo wireless
    • +
    • fixed slow SD cards boot
    • +
    • fixed Allwinner SS driver
    • +
    • fixed bluetooth on Cubietruck, both kernels
    • +
    • fixed wireless driver on H3 boards
    • +
    • fixed R1 switch driver
    • +
    • kernel for Allwinner boards was upgraded to 3.4.112 & 4.5.2
    • +
    • kernel for iMx6 boards was upgraded to 3.14.67 & 4.5.2
    • +
    • kernel for Armada (Clearfog) was upgraded to 3.10.101 & 4.5.2
    • +
    • kernel for Udoo boards was updated to 3.14.67 & 4.4.8
    • +
    • kernel for Guitar (Lemaker) was upgraded to 3.10.101
    • +
    • kernel for H3/sun8i legacy come from new Allwinner updated source (friendlyarm)
    • +
    • added support for Olimex Lime2 eMMC
    • +
    • increased MALI clockspeed on sun8i/legacy
    • +
    • added Armbianmonitor
    • +
    • added Odroid C1, C2(arm64), Nanopi M1, Banana M2+, Pcduino 2 and Pcduino 3. CLI and desktop
    • +
    • added wifi radar to desktop
    • +
    • added preview mainline kernel images for H3 boards (4.6.RC1)
    • +
    • added initrd creation on all Allwinner images
    • +
    • added Hummigboard 2 with working PCI and onboard wireless with legacy kernel 3.14.65
    • +
    • added eMMC installer for H3
    • +
    • added support for IFB and net scheduling for sun7i-legacy
    • +
    • added ax88179_178a USB 3.0 Ethernet driver for sun7i-legacy
    • +
    • hostapd comes as separate package (armbian-hostapd)
    • +
    • changed first boot procedure and force user creation
    • +
    • verbose / no verbose boot works almost on all boards
    • +
    • enabled I2S on sun8i
    • +
    • removed Debian Wheezy from auto build
    • +
    • installing headers autocompile scripts
    • +
    • all images come compressed with 7zip
    • +
    +

    Build script:

    +
      +
    • GCC 5 support for mainline and allwinner legacy
    • +
    • RAW images are not compressed by default
    • +
    • added arm64 building support
    • +
    • added docker as host
    • +
    • Added Belink X2 (H3 based media player), and Roseapple (S500) as WIP target
    • +
    • introducted CLI_TARGET per board
    • +
    • prepared Xenial target
    • +
    • fixed USB redirector building on all kernels
    • +
    • support for Xenial as a build host is 95% ready.
    • +
    • implemented automatic toolchain selection
    • +
    • come cleanup, configurations are subfoldered
    • +
    • extended_deboostrap becomes default
    • +
    +

    Known bugs:

    +
      +
    • Udoo Neo reboots takes a while, 1min+
    • +
    • headers within sun8i needs some fixing
    • +
    • H3 board autodetection fail under certain conditions
    • +
    +

    v5.06 (2016-03-18)

    +
      +
    • increase kernel version to 3.4.111
    • +
    • headers auto creation while install (eases kernel/driver compilation)
    • +
    • improved SD card partitioning to help old/slow cards with wear leveling and garbage collection
    • +
    • Possible to use Ubuntu Xenial Xerus as target
    • +
    • changed behaviour of board leds (green == power, red == warning)
    • +
    • speed improvements for 1st automated reboot
    • +
    • Integrates OverlayFS backport
    • +
    +

    v5.05 (2016-03-08)

    +
      +
    • Auto detection for the Orange Pi 2 does work now
    • +
    • Mali acceleration works for all users not only root
    • +
    • verbose boot logging on 1st boot and after crashes (you can toggle verbose logging using sudo armbianmonitor -b)
    • +
    • more WiFi dongles supported due to backported firmware loader patch
    • +
    • all 3 USB ports on Orange Pi One (Lite) available (2 of them need soldering)
    • +
    • I2S possible on all Orange Pis (compare with the mini tutorial since you need to tweak script.bin)
    • +
    • default display resolution set to 720p60 to fix possible overscan issues on 1st boot
    • +
    • HW accelerated video decoding works for most formats
    • +
    • Booting from eMMC on OPi Plus now possible
    • +
    • Udoo quad images upgraded to 4.4.4
    • +
    +

    v5.04 (2016-03-01)

    +
      +
    • HDMI/DVI works (bug in boot.cmd settings)
    • +
    • Reboot issues fixed (bug in fex settings)
    • +
    • 1-Wire useable (we chose to stay compatible to loboris’ images so the data pin is 37 by default. You’re able to change this in the fex file)
    • +
    • changing display resolution and choosing between HDMI and DVI is now possible with the included h3disp tool (should also work in the stand-alone version with Debian based OS images from loboris/Xunlong). Use sudo h3disp in a terminal to get the idea.
    • +
    • Ethernet issues fixed (combination of kernel and fex fixes)
    • +
    • USB-to-SATA bridge on the Orange Pi Plus works
    • +
    • stability problems on Orange Pi One fixed (due to undervoltage based on wrong fex settings)
    • +
    • problems with 2 USB ports on the PC fixed (wrong kernel config)
    • +
    • Mali400MP acceleration (EGL/GLES) works now
    • +
    • suspend to RAM and resume by power button works now (consumption less than 0.4W without peripherals)
    • +
    • Enforce user account creation before starting the GUI
    • +
    • USB and Ethernet IRQs distributed nicely accross CPU cores
    • +
    • Full HDMI colour-range adjustable/accessible through h3disp utility
    • +
    • already useable as stable headless/server board
    • +
    • rebuilt Cubieboard 1 & 2 with 3.4.110 and 4.4.3
    • +
    • fixed Bluetooth on Cubietruck + rebuild with 3.4.110 and 4.4.3
    • +
    • all new images has no login policy: forced user generation
    • +
    +

    v5.03 (2016-02-20)

    +
      +
    • H3 images rebuilt
    • +
    +

    v5.02 (2016-02-18)

    +
      +
    • H3 images rebuilt
    • +
    +

    v5.01 (2016-02-17)

    + +

    v5.00 (2016-02-12)

    +
      +
    • mainline kernel for Allwinner based boards upgraded to 4.4.1
    • +
    • Allwinner audio driver playback and capture on kernel 4.4.1, UAS, USB OTG, battery readings,
    • +
    • added Marvel Armada kernel 3.10.96, 4.4.1 and patches for changing mPCI to SATA
    • +
    • added Cubox / Hummingboard kernel 4.4.1 (serial console only)
    • +
    • firstrun does autoreboot only if needed: wheezy and some legacy kernels.
    • +
    • added motd to /etc/updated.motd … redesign, added battery info for Allwinner boards, bugfix, coloring
    • +
    • fixed temperature reading on Cubox / Hummingboard legacy kernel
    • +
    • fixed FB turbo building on Allwinner
    • +
    • fixed NAND install on A10 boards (Legacy kernel only)
    • +
    • fixed USB boot, added PWM on mainline
    • +
    • fixed Banana PRO/+ onboard wireless on mainline kernel - running with normal Banana DT.
    • +
    • readded USB sound
    • +
    • added A13 Olimex SOM
    • +
    • added LIRC GPIO receive and send driver for legacy Allwinner
    • +
    • added LED MMC activity to mainline kernels for Cubietruck and Cubieboard A10
    • +
    • build script: option to build images with F2FS root filesystem for Allwinner boards
    • +
    • build script: added alternative kernel for Lemaker Guitar (NEXT), Cubox (DEV)
    • +
    +

    v4.81 (2015-12-28)

    +
      +
    • complete build script rework
    • +
    • new development kernel package linux-image-dev-sunxi (4.4RC6) for Allwinner boards
    • +
    • added Lemaker Guitar, kernel 3.10.55
    • +
    • added Odroid XU3/4, kernel 3.10.94 and mainline 4.2.8
    • +
    • mainline kernel for Allwinner based boards upgraded to 4.3.3
    • +
    • Udoo mainline upgraded to 4.2.8, legacy to 3.14.58
    • +
    • cubox / hummingboard upgraded to 3.14.58, added mainline kernel 4.4
    • +
    • fixed Jessie RTC bug, systemd default on Jessie images
    • +
    +

    v4.70 (2015-11-30)

    +
      +
    • Bugfix update(apt-get update && apt-get upgrade)
    • +
    • small changes and fixes
    • +
    +

    v4.6 (2015-11-24)

    +
      +
    • Update only (apt-get update && apt-get upgrade)
    • +
    • mainline kernel for Allwinner based boards upgraded to 4.2.6
    • +
    • Legacy kernel for Allwinner based boards upgraded to 3.4.110
    • +
    • added new board: Udoo Neo
    • +
    • added USB printer, CAN, CMA, ZSWAP, USB video class, CDROM fs, sensor classs, … to Allwinner mainline kernel
    • +
    • armbian-install scripts rewrite. Now it’s possible to install to any partition.
    • +
    • fixed nand install for Allwinner A10 based boards: Cubieboard 1 / Lime A10
    • +
    • universal upgrade script bugfix / rewrite.
    • +
    • 8 channel HDMI support for legacy Allwinner kernel
    • +
    • unattended upgrade fixed
    • +
    • sunxi tools fixed
    • +
    • added two new options to build script: keep kernel config and use_ccache
    • +
    • added kernel version to motd
    • +
    +

    v4.5 (2015-10-14)

    +
      +
    • mainline kernel upgraded to 4.2.3 for Allwinner based boards
    • +
    • legacy kernel for Allwinner compiled from new sources (linux-sunxi)
    • +
    • udoo mainline upgraded to 4.2.3
    • +
    • cubox / hummingboard upgraded to 3.14.54
    • +
    • changed kernel naming: A10 = linux-image-sun4i, A20 = linux-image-sun7i
    • +
    • new boards: Banana M2, Orange+(A31S), Cubieboard 1, Cubieboard 2 Dual SD, Lime A10
    • +
    • fixed Udoo legacy wireless problems
    • +
    • fixed Jessie boot problems by disabling systemd. It’s possible to re-enable within boot scripts
    • +
    • added ramlog to Jessie because we don’t have systemd anymore
    • +
    • changed wireless driver for Cubietruck and Banana PRO (now it’s ap6210)
    • +
    • added ZRAM to mainline kernel
    • +
    • fixed dvbsky modules
    • +
    +

    and a bunch of small fixes.

    +

    v4.4 (2015-10-01)

    +

    Images:

    +
      +
    • mainline kernel upgrade to 4.2.2 (Allwinner, Udoo Quad),
    • +
    • legacy kernel upgraded to 3.4.109 (Allwinner),
    • +
    • added I2C support and bunch of multimedia modules (DVB) (mainline Allwinner),
    • +
    • Udoo quad images with fixed legacy kernel 3.14.28,
    • +
    • Cubox and Hummingboard kernel upgrade to 3.14.53,
    • +
    • brcmfmac driver fixes for mainline kernel (Banana PRO / Cubietruck)
    • +
    • performance tweak: choosing a closest Debian mirror (Debian images)
    • +
    • added Astrometa DVB firmware and dvb-tools
    • +
    • added Nikkov SPDIF / I2S recent patch (legacy Allwinner)
    • +
    • added patch for rtl8192cu: Add missing case in rtl92cu_get_hw_reg (Lamobo R1)
    • +
    • bigger NAND boot partition on install
    • +
    • install script bug fixes
    • +
    +

    Script:

    +
      +
    • force apt-get update on older rootfs cache,
    • +
    • image harden manipulation security,
    • +
    • packages NAND/FAT/same version install faling fixed,
    • +
    • image shrinking function rework,
    • +
    • better packages installation install checking,
    • +
    • added Debian keys to suppress warnings in debootstrap process,
    • +
    • added fancy progress bars,
    • +
    • added whiptail downloading prior to usage (bugfix).
    • +
    +

    v4.3 (2015-09-17)

    +
      +
    • kernel 4.2 for Allwinner based boards
    • +
    • kernel 4.2 for Udoo Quad
    • +
    • walk-around if ethernet is not detected on some boards due to RTC not set(?)
    • +
    • update is done (semi) automatic if you are using Armbian 4.2. You only need to issue command: apt-get update && apt-get upgrade. If you are coming from older system, check Documentation
    • +
    • U-boot on R1 is now updated to latest stable version (2015.07)
    • +
    • Fixed AW SOM. Working with latest u-boot but you need to build image by yourself.
    • +
    • Enabled whole USB net and HID section in kernel for Allwinner boards v4.2
    • +
    • Fixed upgrade script – only some minor bugs remains.
    • +
    • Fixes to build script that it’s working under Ubuntu 15.04
    • +
    • Adding Bananapi Wireless driver (ap6210) back to legacy kernel
    • +
    • Udoo official kernel (3.14.28) not updated due too many troubles.
    • +
    +

    v4.2 (2015-09-01)

    +

    Images:

    +
      +
    • Upgraded NAND / SATA installer. Possible to install to SATA/NAND boot in one step.
    • +
    • Easy kernel switching between old 3.4 and 4.x
    • +
    • Automatic kernel updating (to disable comment armbian repo /etc/apt/sources.list)
    • +
    • Allwinner boards share one 4.x kernel and two 3.4
    • +
    • All boards share the same revision number
    • +
    • One minimal Ubuntu Desktop per board (Wicd, Firefox, Word)
    • +
    • u-boot v2015.07 for most boards
    • +
    • Aufs file system support
    • +
    • kernel 4.1.6 and 3.4.108
    • +
    • Added Orangepi Mini, Cubieboard 1 (4.x only), Udoo with official kernel
    • +
    • Repository for Wheezy, Jessie and Trusty
    • +
    • enabled USB audio in kernel 4.x
    • +
    • kernel headers fixed. No need to rebuild when you update the kernel.
    • +
    • fixed boot scripts that can load from FAT partition too
    • +
    • removed Cubox binnary repository because of troubles
    • +
    • Docker support (kernel 4.x). Already here for a while / forget to mention.
    • +
    • nodm change default login
    • +
    +

    Build script:

    +
      +
    • changed structure: sources now in folder sources, output is what we produce, deb in one folder
    • +
    • expanded desktop part
    • +
    • possible to build all images at once, create package repository
    • +
    • SD card initial size is 4Gb, variable transfered into configuration.sh
    • +
    • Avaliable board list is now created from file configuration.sh
    • +
    • Fixed image shrinking problem
    • +
    • Patching part rework
    • +
    • Using first FAT boot partition now fixes boot scripts
    • +
    • Uboot TAG moved to configuration.sh and differs for some boards
    • +
    • new variables for source branches. Only too remove errors when checking out
    • +
    +

    v4.1 (2015-08-05)

    +
      +
    • Added desktop image
    • +
    • U-Boot 2015.07 with many new features
    • +
    • Added auto system update via repository apt.armbian.com
    • +
    • Root password change is initialized at first boot.
    • +
    • 3.4.108 kernel fixes, 4.1.4 Allwinner Security System
    • +
    +

    v4.0 (2015-07-12)

    +
      +
    • Fixed stability issues, temperature display in 4.x
    • +
    • Kernel upgrades to 3.4.108 and 4.1.2
    • +
    +

    v3.9 (2015-06-11)

    +
      +
    • Bugfix release
    • +
    • Kernel 4.0.5 traffic control support
    • +
    • SATA / USB install fixed on kernel 4.x
    • +
    • Added 256Mb emergency swap area, created automatically @first boot
    • +
    +

    v3.8 (2015-05-21)

    +
      +
    • Bugfix release: Cubietruck images successfully booted on Cubietruck. I waited for automatic reboot than tested remote login.
    • +
    • Kernel 4.0.4 added support for power on/off button
    • +
    • Both: Jessie fixed, Ethernet init fixed (uboot)
    • +
    • armbian.com introduction
    • +
    +

    v3.7 (2015-05-14)

    +
      +
    • Kernel 4.0.3 some new functionality
    • +
    • Kernel 3.4.107 added sunxi display manager to change FB on demand
    • +
    • Both: Ubuntu and jessie install errors fixed, removed busybox-syslogd and changed to default logger due to problems in Jessie and Ubuntu, apt-get upgrade fixed, documentations update, Uboot fixed to 2015.4 – no more from dev branch
    • +
    • Build script rework - image size shrink to actual size, possible to have fat boot partition on SD card, several script bug fixes
    • +
    +

    v3.6 (2015-04-29)

    +
      +
    • Kernel 3.19.6
    • +
    • Kernel 3.4.107 with better BT loading solution
    • +
    +

    v3.5 (2015-04-18)

    +
      +
    • Kernel 3.19.4: fixed AP mode, fixed USB, added 8192CU module
    • +
    • Common: apt-get upgrade ready but not enabled yet, serial console fixed, fixed hostapd under jessie, easy kernel switching, latest patched hostapd for best performance – normal and for realtek adaptors, auto IO scheduler script
    • +
    • Build script: everything packed as DEB
    • +
    +

    v3.4 (2015-03-28)

    +
      +
    • Kernel 3.19.3: docker support, apple hid, pmp, nfsd, sata peformance fix
    • +
    • Kernel 3.4.106: pmp, a20_tp - soc temp sensor
    • +
    • Common: console setup fixed, headers bugfix, nand install fix
    • +
    • Build script: kernel build only, custom packets install, hardware accelerated desktop build as option
    • +
    +

    v3.3 (2015-02-28)

    +
      +
    • Kernel 3.19.0: many new functionality and fixes.
    • +
    • Bugfixes: CT wireless works in all kernels
    • +
    +

    v3.2 (2015-01-24)

    +
      +
    • Possible to compile external modules on both kernels
    • +
    • Kernel 3.19.0 RC5
    • +
    • Bugfixes: install script, headers, bashrc, spi
    • +
    +

    v3.1 (2015-01-16)

    +
      +
    • Kernel 3.19.0 RC4
    • +
    • Added Cubieboard 1 images
    • +
    • Dualboot for CB2 and CT dropped due to u-boot change. Now separate images.
    • +
    • New user friendly SATA + USB installer, also on mainline
    • +
    +

    v3.0 (2014-12-29)

    +
      +
    • Kernel 3.18.1 for mainline image
    • +
    • Added Ubuntu Trusty (14.04 LTS) image
    • +
    • Bugfixes: auto packages update
    • +
    +

    v2.9 (2014-12-03)

    +
      +
    • Kernel 3.4.105 with new MALI driver and other fixes
    • +
    • Added: Jessie image
    • +
    • Major build script rewrite - much faster image building
    • +
    • Fixed: failed MIN/MAX settings
    • +
    +

    v2.8 (2014-10-17)

    +
      +
    • Added: ondemand governor, fhandle, squashfs and btrfs
    • +
    • Removed: bootsplash, lvm, version numbering in issue
    • +
    • Fixed: custom scripts, Jessie upgrade
    • +
    • Disabled: BT firmware loading, enable back with: insserv brcm40183-patch
    • +
    • Added working driver for RT 8188C, 8192C
    • +
    +

    v2.7 (2014-10-01)

    +
      +
    • Kernel 3.4.104
    • +
    • Automatic Debian system updates
    • +
    • VGA output is now default but if HDMI is attached at first boot than it switch to HDMI for good. After first restart!
    • +
    • Fixed NAND install script. /boot is mounted by default. Kernel upgrade is now the same as on SD systems.
    • +
    • Cubieboard2 - disabled Cubietruck dedicated scripts (BT firmware, LED disable)
    • +
    • Added network bonding and configuration for “notebook” mode (/etc/network/interfaces.bonding)
    • +
    • IR receiver is preconfigured with default driver and LG remote (/etc/lirc/lircd.conf), advanced driver is present but disabled
    • +
    • Added SPI and LVM functionality
    • +
    • Added Debian logo boot splash image
    • +
    • Added build essentials package
    • +
    +

    v2.6 (2014-08-22)

    +
      +
    • Kernel 3.4.103 and 3.17.0-RC1
    • +
    • Added GPIO patch (only for 3.4.103)
    • +
    +

    v2.5 (2014-08-02)

    +
      +
    • Kernel 3.4.101 and 3.16.0-RC4
    • +
    • major build script rewrite
    • +
    +

    v2.4 (2014-07-11)

    +
      +
    • Kernel 3.4.98
    • +
    • default root password (1234) expires at first login
    • +
    • build script rewrite, now 100% non-interactive process, time zone as config option
    • +
    • bug fixes: removed non-existing links in /lib/modules
    • +
    +

    v2.3 (2014-07-02)

    +
      +
    • Kernel 3.4.96
    • +
    • cpuinfo serial number added
    • +
    • bug fixes: stability issues - downclocked to factory defaults, root SSH login enabled in Jessie, dedicated core for eth0 fix
    • +
    • disp_vsync kernel patch
    • +
    +

    v2.2 (2014-06-26)

    +
      +
    • Kernel 3.4.94
    • +
    • Added Jessie distro image
    • +
    • Updated hostapd, bashrc, build script
    • +
    • bug fixes: disabled upgrade and best mirror search @firstboot, bluetooth enabler fix
    • +
    • MD5 hash image protection
    • +
    +

    v2.1 (2014-06-13)

    +
      +
    • Kernel 3.4.93
    • +
    • Onboard Bluetooth finally works
    • +
    • Small performance fix
    • +
    • Allwinner Security System cryptographic accelerator
    • +
    +

    v2.0 (2014-06-02)

    +
      +
    • Kernel 3.4.91 with many fixes
    • +
    • Cubieboard 2 stability issues fix
    • +
    • eth0 interrupts are using dedicated core
    • +
    • Global bashrc /etc/bash.bashrc
    • +
    • Verbose output and package upgrade @ first run
    • +
    +

    v1.9 (2014-04-27)

    +
      +
    • Kernel headers included
    • +
    • Clustering support
    • +
    • Advanced IR driver with RAW RX and TX
    • +
    • Bluetooth ready (working only with supported USB devices)
    • +
    • Bugfixes: VLAN, login script, build script
    • +
    • New packages: lirc, bluetooth
    • +
    +

    v1.8 (2014-03-27)

    +
      +
    • Kernel 3.4.79
    • +
    • Alsa I2S patch + basic ALSA utils
    • +
    • Performance tweaks: CPU O.C. to 1.2Ghz, IO scheduler NOOP for SD, CFQ for sda, journal data writeback enabled
    • +
    • Avaliable memory = 2000MB
    • +
    • Minimized console output at boot
    • +
    • MAC address from chip ID, manual optional
    • +
    • Latest (Access point) hostapd, 2.1 final release
    • +
    • Login script shows current CPU temp, hard drive temp & actual free memory
    • +
    • Fastest Debian mirror auto selection @first boot
    • +
    • New packages: alsa-utils netselect-apt sysfsutils hddtemp bc
    • +
    +

    v1.7 (2014-02-26)

    +
      +
    • Flash media performance tweaks, reduced writings, tmp & logging to RAM with ramlog app – sync logs on shutdown
    • +
    • SATA install script
    • +
    • Dynamic MOTD: Cubieboard / Cubietruck
    • +
    • Disabled Debian logo at startup
    • +
    • New packages: figlet toilet screen hdparm libfuse2 ntfs-3g bash-completion
    • +
    +

    v1.6 (2014-02-09)

    +
      +
    • Added support for Cubieboard 2
    • +
    • Build script creates separate images for VGA and HDMI
    • +
    • NAND install script added support for Cubieboard 2
    • +
    +

    v1.52 (2014-02-07)

    +
      +
    • Various kernel tweaks, more modules enabled
    • +
    • Root filesystem can be moved to USB drive
    • +
    • Bugfixes: NAND install script
    • +
    +

    v1.5 (2014-01-22)

    +
      +
    • Hotspot Wifi Access Point / Hostapd 2.1
    • +
    • Bugfixes: MAC creation script, SSH keys creation, removed double packages, …
    • +
    • Graphics desktop environment upgrade ready
    • +
    +

    v1.4 (2014-01-12)

    +
      +
    • Patwood’s kernel 3.4.75+ with many features
    • +
    • Optimized CPU frequency scaling 480-1010Mhz with interactive governor
    • +
    • NAND install script included
    • +
    • Cubietruck MOTD
    • +
    • USB redirector – for sharing USB over TCP/IP
    • +
    +

    v1.3 (2014-01-03)

    +
      +
    • CPU frequency scaling 30-1000Mhz
    • +
    • Patch for gpio
    • +
    +

    v1.23 (2014-01-01)

    +
      +
    • added HDMI version
    • +
    • added sunxi-tools
    • +
    • build.sh transfered to Github repository
    • +
    • disabled LED blinking
    • +
    +

    v1.2 (2013-12-26)

    +
      +
    • changed kernel and hardware config repository
    • +
    • kernel 3.4.61+
    • +
    • wi-fi working
    • +
    • updated manual how-to
    • +
    +

    v1.0 (2013-12-24)

    +
      +
    • total memory available is 2G (disabled memory for GPU by default)
    • +
    • gigabit ethernet is fully operational
    • +
    • sata driver enabled
    • +
    • root filesystem autoresize
    • +
    • MAC address fixed at first boot
    • +
    • Kernel 3.4.75
    • +
    • root password=1234
    • +
    • Bugs: wifi and BT not working
    • +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Advanced-Features/index.html b/611/User-Guide_Advanced-Features/index.html new file mode 100644 index 000000000..04e6e1043 --- /dev/null +++ b/611/User-Guide_Advanced-Features/index.html @@ -0,0 +1,2253 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Advanced Features - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Advanced Features

    +

    How to switch kernels?

    +
    Bash
    armbian-config --cmd SY015
    +
    +

    How to build a wireless driver?

    +

    Install kernel headers:

    +
    Text Only
    1
    armbian-config --cmd SY004
    +
    +

    Download driver sources:

    +
    Text Only
    1
    +2
        git clone https://github.com/morrownr/8821au-20210708.git
    +    cd 8821au-20210708
    +
    +

    Build and install:

    +
    Text Only
    1
    +2
        make
    +    make install
    +
    +
    +Build log +
    Text Only
      1
    +  2
    +  3
    +  4
    +  5
    +  6
    +  7
    +  8
    +  9
    + 10
    + 11
    + 12
    + 13
    + 14
    + 15
    + 16
    + 17
    + 18
    + 19
    + 20
    + 21
    + 22
    + 23
    + 24
    + 25
    + 26
    + 27
    + 28
    + 29
    + 30
    + 31
    + 32
    + 33
    + 34
    + 35
    + 36
    + 37
    + 38
    + 39
    + 40
    + 41
    + 42
    + 43
    + 44
    + 45
    + 46
    + 47
    + 48
    + 49
    + 50
    + 51
    + 52
    + 53
    + 54
    + 55
    + 56
    + 57
    + 58
    + 59
    + 60
    + 61
    + 62
    + 63
    + 64
    + 65
    + 66
    + 67
    + 68
    + 69
    + 70
    + 71
    + 72
    + 73
    + 74
    + 75
    + 76
    + 77
    + 78
    + 79
    + 80
    + 81
    + 82
    + 83
    + 84
    + 85
    + 86
    + 87
    + 88
    + 89
    + 90
    + 91
    + 92
    + 93
    + 94
    + 95
    + 96
    + 97
    + 98
    + 99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +156
    +157
    +158
    +159
    +160
    +161
    +162
    +163
    +164
    make ARCH=arm64 CROSS_COMPILE= -C /lib/modules/6.6.62-current-sunxi64/build M=/root/8821au-20210708  modules
    +make[1]: Entering directory '/usr/src/linux-headers-6.6.62-current-sunxi64'
    +  CC [M]  /root/8821au-20210708/core/rtw_cmd.o
    +  CC [M]  /root/8821au-20210708/core/rtw_security.o
    +  CC [M]  /root/8821au-20210708/core/rtw_debug.o
    +  CC [M]  /root/8821au-20210708/core/rtw_io.o
    +  CC [M]  /root/8821au-20210708/core/rtw_ioctl_query.o
    +  CC [M]  /root/8821au-20210708/core/rtw_ioctl_set.o
    +  CC [M]  /root/8821au-20210708/core/rtw_ieee80211.o
    +  CC [M]  /root/8821au-20210708/core/rtw_mlme.o
    +  CC [M]  /root/8821au-20210708/core/rtw_mlme_ext.o
    +  CC [M]  /root/8821au-20210708/core/rtw_mi.o
    +  CC [M]  /root/8821au-20210708/core/rtw_wlan_util.o
    +  CC [M]  /root/8821au-20210708/core/rtw_vht.o
    +  CC [M]  /root/8821au-20210708/core/rtw_pwrctrl.o
    +  CC [M]  /root/8821au-20210708/core/rtw_rf.o
    +  CC [M]  /root/8821au-20210708/core/rtw_chplan.o
    +  CC [M]  /root/8821au-20210708/core/monitor/rtw_radiotap.o
    +  CC [M]  /root/8821au-20210708/core/rtw_recv.o
    +  CC [M]  /root/8821au-20210708/core/rtw_sta_mgt.o
    +  CC [M]  /root/8821au-20210708/core/rtw_ap.o
    +  CC [M]  /root/8821au-20210708/core/wds/rtw_wds.o
    +  CC [M]  /root/8821au-20210708/core/mesh/rtw_mesh.o
    +  CC [M]  /root/8821au-20210708/core/mesh/rtw_mesh_pathtbl.o
    +  CC [M]  /root/8821au-20210708/core/mesh/rtw_mesh_hwmp.o
    +  CC [M]  /root/8821au-20210708/core/rtw_xmit.o
    +  CC [M]  /root/8821au-20210708/core/rtw_p2p.o
    +  CC [M]  /root/8821au-20210708/core/rtw_rson.o
    +  CC [M]  /root/8821au-20210708/core/rtw_tdls.o
    +  CC [M]  /root/8821au-20210708/core/rtw_br_ext.o
    +  CC [M]  /root/8821au-20210708/core/rtw_iol.o
    +  CC [M]  /root/8821au-20210708/core/rtw_sreset.o
    +  CC [M]  /root/8821au-20210708/core/rtw_btcoex_wifionly.o
    +  CC [M]  /root/8821au-20210708/core/rtw_btcoex.o
    +  CC [M]  /root/8821au-20210708/core/rtw_beamforming.o
    +  CC [M]  /root/8821au-20210708/core/rtw_odm.o
    +  CC [M]  /root/8821au-20210708/core/rtw_rm.o
    +  CC [M]  /root/8821au-20210708/core/rtw_rm_fsm.o
    +  CC [M]  /root/8821au-20210708/core/rtw_ft.o
    +  CC [M]  /root/8821au-20210708/core/rtw_wnm.o
    +  CC [M]  /root/8821au-20210708/core/rtw_mbo.o
    +  CC [M]  /root/8821au-20210708/core/rtw_rm_util.o
    +  CC [M]  /root/8821au-20210708/core/efuse/rtw_efuse.o
    +  CC [M]  /root/8821au-20210708/core/rtw_roch.o
    +  CC [M]  /root/8821au-20210708/core/crypto/aes-internal.o
    +  CC [M]  /root/8821au-20210708/core/crypto/aes-internal-enc.o
    +  CC [M]  /root/8821au-20210708/core/crypto/aes-gcm.o
    +  CC [M]  /root/8821au-20210708/core/crypto/aes-ccm.o
    +  CC [M]  /root/8821au-20210708/core/crypto/aes-omac1.o
    +  CC [M]  /root/8821au-20210708/core/crypto/ccmp.o
    +  CC [M]  /root/8821au-20210708/core/crypto/gcmp.o
    +  CC [M]  /root/8821au-20210708/core/crypto/aes-siv.o
    +  CC [M]  /root/8821au-20210708/core/crypto/aes-ctr.o
    +  CC [M]  /root/8821au-20210708/core/crypto/sha256-internal.o
    +  CC [M]  /root/8821au-20210708/core/crypto/sha256.o
    +  CC [M]  /root/8821au-20210708/core/crypto/sha256-prf.o
    +  CC [M]  /root/8821au-20210708/core/crypto/rtw_crypto_wrap.o
    +  CC [M]  /root/8821au-20210708/core/rtw_swcrypto.o
    +  CC [M]  /root/8821au-20210708/os_dep/osdep_service.o
    +  CC [M]  /root/8821au-20210708/os_dep/linux/os_intfs.o
    +  CC [M]  /root/8821au-20210708/os_dep/linux/usb_intf.o
    +  CC [M]  /root/8821au-20210708/os_dep/linux/usb_ops_linux.o
    +  CC [M]  /root/8821au-20210708/os_dep/linux/ioctl_linux.o
    +  CC [M]  /root/8821au-20210708/os_dep/linux/xmit_linux.o
    +  CC [M]  /root/8821au-20210708/os_dep/linux/mlme_linux.o
    +  CC [M]  /root/8821au-20210708/os_dep/linux/recv_linux.o
    +  CC [M]  /root/8821au-20210708/os_dep/linux/ioctl_cfg80211.o
    +  CC [M]  /root/8821au-20210708/os_dep/linux/rtw_cfgvendor.o
    +  CC [M]  /root/8821au-20210708/os_dep/linux/wifi_regd.o
    +  CC [M]  /root/8821au-20210708/os_dep/linux/rtw_android.o
    +  CC [M]  /root/8821au-20210708/os_dep/linux/rtw_proc.o
    +  CC [M]  /root/8821au-20210708/os_dep/linux/nlrtw.o
    +  CC [M]  /root/8821au-20210708/os_dep/linux/rtw_rhashtable.o
    +  CC [M]  /root/8821au-20210708/hal/hal_intf.o
    +  CC [M]  /root/8821au-20210708/hal/hal_com.o
    +  CC [M]  /root/8821au-20210708/hal/hal_com_phycfg.o
    +  CC [M]  /root/8821au-20210708/hal/hal_phy.o
    +  CC [M]  /root/8821au-20210708/hal/hal_dm.o
    +  CC [M]  /root/8821au-20210708/hal/hal_dm_acs.o
    +  CC [M]  /root/8821au-20210708/hal/hal_btcoex_wifionly.o
    +  CC [M]  /root/8821au-20210708/hal/hal_btcoex.o
    +  CC [M]  /root/8821au-20210708/hal/hal_mp.o
    +  CC [M]  /root/8821au-20210708/hal/hal_mcc.o
    +  CC [M]  /root/8821au-20210708/hal/hal_hci/hal_usb.o
    +  CC [M]  /root/8821au-20210708/hal/led/hal_led.o
    +  CC [M]  /root/8821au-20210708/hal/led/hal_usb_led.o
    +  CC [M]  /root/8821au-20210708/hal/HalPwrSeqCmd.o
    +  CC [M]  /root/8821au-20210708/hal/rtl8812a/Hal8812PwrSeq.o
    +  CC [M]  /root/8821au-20210708/hal/rtl8812a/Hal8821APwrSeq.o
    +  CC [M]  /root/8821au-20210708/hal/rtl8812a/rtl8812a_xmit.o
    +  CC [M]  /root/8821au-20210708/hal/rtl8812a/rtl8812a_sreset.o
    +  CC [M]  /root/8821au-20210708/hal/rtl8812a/rtl8812a_hal_init.o
    +  CC [M]  /root/8821au-20210708/hal/rtl8812a/rtl8812a_phycfg.o
    +  CC [M]  /root/8821au-20210708/hal/rtl8812a/rtl8812a_rf6052.o
    +  CC [M]  /root/8821au-20210708/hal/rtl8812a/rtl8812a_dm.o
    +  CC [M]  /root/8821au-20210708/hal/rtl8812a/rtl8812a_rxdesc.o
    +  CC [M]  /root/8821au-20210708/hal/rtl8812a/rtl8812a_cmd.o
    +  CC [M]  /root/8821au-20210708/hal/rtl8812a/usb/usb_halinit.o
    +  CC [M]  /root/8821au-20210708/hal/rtl8812a/usb/rtl8812au_led.o
    +  CC [M]  /root/8821au-20210708/hal/rtl8812a/usb/rtl8812au_xmit.o
    +  CC [M]  /root/8821au-20210708/hal/rtl8812a/usb/rtl8812au_recv.o
    +  CC [M]  /root/8821au-20210708/hal/rtl8812a/usb/usb_ops_linux.o
    +  CC [M]  /root/8821au-20210708/hal/efuse/rtl8812a/HalEfuseMask8821A_USB.o
    +  CC [M]  /root/8821au-20210708/hal/rtl8812a/hal8821a_fw.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_debug.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_antdiv.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_soml.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_smt_ant.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_antdect.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_interface.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_phystatus.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_hwconfig.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_dig.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_pathdiv.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_rainfo.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_dynamictxpower.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_adaptivity.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_cfotracking.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_noisemonitor.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_beamforming.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_direct_bf.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_dfs.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/txbf/halcomtxbf.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/txbf/haltxbfinterface.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/txbf/phydm_hal_txbf_api.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_adc_sampling.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_ccx.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_psd.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_primary_cca.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_cck_pd.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_rssi_monitor.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_auto_dbg.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_math_lib.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_api.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_pow_train.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_lna_sat.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_pmac_tx_setting.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_mp.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/phydm_cck_rx_pathdiv.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/halrf/halrf.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/halrf/halrf_debug.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/halrf/halphyrf_ce.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/halrf/halrf_powertracking_ce.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/halrf/halrf_powertracking.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/halrf/halrf_kfree.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/halrf/halrf_psd.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/rtl8821a/halhwimg8821a_mac.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/rtl8821a/halhwimg8821a_bb.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/rtl8821a/halhwimg8821a_rf.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/halrf/rtl8812a/halrf_8812a_ce.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/halrf/rtl8821a/halrf_8821a_ce.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/rtl8821a/phydm_regconfig8821a.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/rtl8821a/phydm_rtl8821a.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/halrf/rtl8821a/halrf_iqk_8821a_ce.o
    +  CC [M]  /root/8821au-20210708/hal/phydm/txbf/haltxbfjaguar.o
    +  CC [M]  /root/8821au-20210708/hal/btc/halbtc8821a1ant.o
    +  CC [M]  /root/8821au-20210708/hal/btc/halbtc8821a2ant.o
    +  CC [M]  /root/8821au-20210708/platform/platform_ops.o
    +  LD [M]  /root/8821au-20210708/8821au.o
    +  MODPOST /root/8821au-20210708/Module.symvers
    +  CC [M]  /root/8821au-20210708/8821au.mod.o
    +  LD [M]  /root/8821au-20210708/8821au.ko
    +make[1]: Leaving directory '/usr/src/linux-headers-6.6.62-current-sunxi64'
    +
    +
    +

    Load driver for test

    +
    Text Only
    1
    insmod 8821au.ko
    +
    +

    Check dmesg and the last entry will be:

    +
    Text Only
    1
    usbcore: registered new interface driver rtl8821au
    +
    +

    Plug the USB wireless adaptor and proceed with network configuration

    +

    How to install Docker?

    +

    Minimal:

    +
    Bash
    armbian-config --CON01
    +
    +

    Full featured:

    +
    Bash
    armbian-config --CON02
    +
    +

    Test if Docker works correctly:

    +
    Bash
    docker run hello-world
    +
    +

    If you get that kind of output, then Docker install went fine:

    +
    Bash
    1
    +2
    Hello from Docker!
    +This message shows that your installation appears to be working correctly.
    +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Armbian-Config/Localisation/index.html b/611/User-Guide_Armbian-Config/Localisation/index.html new file mode 100644 index 000000000..460524d61 --- /dev/null +++ b/611/User-Guide_Armbian-Config/Localisation/index.html @@ -0,0 +1,1921 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Localisation - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Localisation

    +
    +

    Change Global timezone

    +

    Command: +

    Text Only
    armbian-config --cmd LO001
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Change Locales reconfigure the language and character set

    +

    Command: +

    Text Only
    armbian-config --cmd LO002
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Change Keyboard layout

    +

    Command: +

    Text Only
    armbian-config --cmd LO003
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Change System Hostname

    +

    Command: +

    Text Only
    armbian-config --cmd LO005
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Armbian-Config/Network/index.html b/611/User-Guide_Armbian-Config/Network/index.html new file mode 100644 index 000000000..8f21304cf --- /dev/null +++ b/611/User-Guide_Armbian-Config/Network/index.html @@ -0,0 +1,2049 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Network - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Fixed and wireless network settings

    +
    +

    Configure network interfaces

    +
    +

    Add / change interface

    + +
    graph LR
    +  A[Network] --> B[Add / Change interface];
    +  A[Network] --> O[Revert to defaults];
    +  A[Network] --> P[Show configuration];
    +  B ---->E[Wired];
    +  B ---->F[Wireless];
    +  E -->R[DHCP];
    +  E -->T[Static];
    +  E -->S[Spoof MAC];
    +  F -->X[Station];
    +  F -->W[Access point]; 
    + + +

    Command: +

    Text Only
    armbian-config --cmd NE002
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    + +
    +
    +
    +

    In order to configure your network devices, they need to be supported the kernel.

    +

    To verify, use command:

    +
    Bash
    ip addr
    +
    +

    It is usually something like eth0, enp4s3 or lan.

    +
    +
    +

    In order to configure your wireless network devices, they need to be supported the kernel.

    +

    To verify, use command:

    +
    Bash
    iw dev | awk '$1=="Interface"{print $2}'
    +
    +

    It is usually something like wlan0, wlo1 or wlx12334c47dec3. If you get blank response, it means your WiFi device / dongle is not supported by the kernel.

    +
    +
    +
    + + +
    +

    Revert to Armbian defaults

    +

    Command: +

    Text Only
    armbian-config --cmd NE003
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Show configuration

    +

    Command: +

    Text Only
    armbian-config --cmd NE004
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Show active status

    +

    Command: +

    Text Only
    armbian-config --cmd NE005
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    WireGuard VPN client / server

    + +

    WireGuard VPN client / server

    + + + +

    WireGuard is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography. It aims to be faster, simpler, leaner, and more useful than IPsec, while avoiding the massive headache. It intends to be considerably more performant than OpenVPN. WireGuard is designed as a general purpose VPN for running on embedded interfaces and super computers alike, fit for many different circumstances. Initially released for the Linux kernel, it is now cross-platform (Windows, macOS, BSD, iOS, Android) and widely deployable. Regarded as the most secure, easiest to use, and simplest VPN solution in the industry.

    + + +

    Command: +

    Text Only
    armbian-config --cmd WG001
    +

    +

    Author: @armbian

    +

    Status: Enabled

    + +
    +
    +
    +

    Remember to open/forward the port 51820 (UDP) through NAT on your router.

    +
    +
    +
      +
    • Install directory: /armbian/wireguard
    • +
    • Site configuration directory: /armbian/wireguard/config
    • +
    +
    +
    +
    Bash
    docker logs -f wireguard
    +
    +
    +
    +
    +

    Install server and enable private network on a client

    +
      +
    1. Install Wireguard server
    2. +
    3. It will asks you for peer keywords. It will make a profile for each peer
    4. +
    5. Download client to your PC, server or mobile phone. Scan OR code or copy credentials to the client.
    6. +
    +

    Enjoy private network! Its that easy.

    +

    More informations:

    +

    https://docs.linuxserver.io/images/docker-wireguard/

    + + +
    +

    WireGuard remove

    +

    This operation will remove WireGuard

    +

    Command: +

    Text Only
    armbian-config --cmd WG002
    +

    +

    Author: @armbian

    +

    Status: Enabled

    +
    +

    WireGuard clients QR codes

    +

    Command: +

    Text Only
    armbian-config --cmd WG003
    +

    +

    Author: @armbian

    +

    Status: Enabled

    +
    +

    WireGuard purge with data folder

    +

    This operation will purge WireGuard with data folder

    +

    Command: +

    Text Only
    armbian-config --cmd WG004
    +

    +

    Author: @armbian

    +

    Status: Enabled

    +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Armbian-Config/System/index.html b/611/User-Guide_Armbian-Config/System/index.html new file mode 100644 index 000000000..a036fcdb0 --- /dev/null +++ b/611/User-Guide_Armbian-Config/System/index.html @@ -0,0 +1,2707 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + System - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    System wide and admin settings

    +
    +

    Alternative kernels, headers, rolling updates, overlays

    +
    +

    Install alternative kernels

    +

    Switching between kernels might change functionality of your device.

    +

    It might fail to boot!

    +

    Command: +

    Text Only
    armbian-config --cmd SY201
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Install Linux headers

    +

    Command: +

    Text Only
    armbian-config --cmd SY204
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Remove Linux headers

    +

    Command: +

    Text Only
    armbian-config --cmd SY205
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Manage device tree overlays

    +

    Command: +

    Text Only
    armbian-config --cmd SY210
    +

    +

    Author: @viraniac @igorpecovnik

    +

    Status: Stable

    +
    +

    Select Odroid board configuration

    +

    Command: +

    Text Only
    armbian-config --cmd SY300
    +

    +

    Author:

    +

    Status: Preview

    +
    +

    Edit the boot environment

    +

    This will open /boot/armbianEnv.txt file to edit +CTRL+S to save +CTLR+X to exit +would you like to continue?

    +

    Command: +

    Text Only
    armbian-config --cmd SY010
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Install to internal media, ZFS, NFS, read-only rootfs

    +
    +

    Install to internal storage

    +

    Command: +

    Text Only
    armbian-config --cmd SY001
    +

    +

    Author: @igorpecovnik

    +

    Status: Preview

    +
    +

    ZFS filesystem - enable support

    +

    Command: +

    Text Only
    armbian-config --cmd SY220
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    ZFS filesystem - remove support

    +

    Command: +

    Text Only
    armbian-config --cmd SY221
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Enable read only filesystem

    +

    Command: +

    Text Only
    armbian-config --cmd SY007
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Disable read only filesystem

    +

    Command: +

    Text Only
    armbian-config --cmd SY008
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Enable Network filesystem (NFS) support

    +

    Command: +

    Text Only
    armbian-config --cmd NFS01
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Disable Network filesystem (NFS) support

    +

    Command: +

    Text Only
    armbian-config --cmd NFS02
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Manage NFS Server

    +
    +

    Enable network filesystem (NFS) daemon

    +

    Command: +

    Text Only
    armbian-config --cmd NFS06
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Configure network filesystem (NFS) daemon

    +

    Command: +

    Text Only
    armbian-config --cmd NFS07
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Remove network filesystem (NFS) daemon

    +

    Command: +

    Text Only
    armbian-config --cmd NFS08
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Show network filesystem (NFS) daemon clients

    +

    Command: +

    Text Only
    armbian-config --cmd NFS09
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Manage NFS Client

    +
    +

    Find NFS servers in subnet and mount shares

    +

    Command: +

    Text Only
    armbian-config --cmd NFS21
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Manage SSH daemon options, enable 2FA

    +
    +

    Disable root login

    +

    Command: +

    Text Only
    armbian-config --cmd SY101
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Enable root login

    +

    Command: +

    Text Only
    armbian-config --cmd SY102
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Disable password login

    +

    Command: +

    Text Only
    armbian-config --cmd SY103
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Enable password login

    +

    Command: +

    Text Only
    armbian-config --cmd SY104
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Disable Public key authentication login

    +

    Command: +

    Text Only
    armbian-config --cmd SY105
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Enable Public key authentication login

    +

    Command: +

    Text Only
    armbian-config --cmd SY106
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Disable OTP authentication

    +

    Command: +

    Text Only
    armbian-config --cmd SY107
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Enable OTP authentication

    +

    Command: +

    Text Only
    armbian-config --cmd SY108
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Generate new OTP authentication QR code

    +

    Command: +

    Text Only
    armbian-config --cmd SY109
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Show OTP authentication QR code

    +

    Command: +

    Text Only
    armbian-config --cmd SY110
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Disable last login banner

    +

    Command: +

    Text Only
    armbian-config --cmd SY111
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Enable last login banner

    +

    Command: +

    Text Only
    armbian-config --cmd SY112
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Sandboxed & containerised SSH server

    + +

    Sandboxed & containerised SSH server

    + + + +

    Sandboxed & containerised SSH server allows ssh access without giving keys to the entire server. Giving ssh access via private key often means giving full access to the server. This container creates a limited and sandboxed environment that others can ssh into. The users only have access to the folders mapped and the processes running inside this container.

    + + +

    This operation will install SSH server.

    +

    Command: +

    Text Only
    armbian-config --cmd SSH200
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    + +
    +
    +
    +
      +
    • ssh username@<your.IP> -p 2222
    • +
    +
    +
    +
      +
    • Install directory: /armbian/openssh-server
    • +
    • Configuration directory: /armbian/openssh-server/config
    • +
    • Shared storage directory: USER_DEFINED
    • +
    +
    +
    +
    Bash
    docker logs -f openssh-server
    +
    +
    +
    +
    + + +
    +

    Remove sandboxed SSH server

    +

    This operation will remove SSH server.

    +

    Command: +

    Text Only
    armbian-config --cmd SSH201
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Purge sandboxed SSH server with data folder

    +

    This operation will purge SSH server with data folder.

    +

    Command: +

    Text Only
    armbian-config --cmd SSH202
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Change shell, adjust MOTD

    +
    +

    Change shell system wide to BASH

    +

    This will switch system wide shell to BASH

    +

    Command: +

    Text Only
    armbian-config --cmd SY005
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Change shell system wide to ZSH

    +

    This will switch system wide shell to ZSH

    +

    Command: +

    Text Only
    armbian-config --cmd SY006
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Adjust welcome screen (motd)

    +

    Command: +

    Text Only
    armbian-config --cmd SY009
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    OS updates and distribution upgrades

    +

    Status: Active

    +
    +

    Enable Armbian firmware upgrades

    +

    This will enable Armbian kernel upgrades that are currently put on hold.

    +

    Command: +

    Text Only
    armbian-config --cmd SY202
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Disable Armbian kernel upgrades

    +

    Disable Armbian kernel/firmware upgrades

    +

    Command: +

    Text Only
    armbian-config --cmd SY203
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Switch system to rolling packages repository

    +

    This will switch OS to rolling releases.

    +

    Command: +

    Text Only
    armbian-config --cmd SY206
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Switch system to stable packages repository

    +

    This will switch OS to stable releases

    +

    Command: +

    Text Only
    armbian-config --cmd SY207
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Enable automating Docker container base images updating

    + +

    Enable automating Docker container base images updating

    + + + +

    Watchtower is an application that will monitor your running Docker containers and watch for changes to the images that those containers were originally started from. If watchtower detects that an image has changed, it will automatically restart the container using the new image.

    + + +

    Command: +

    Text Only
    armbian-config --cmd WTC001
    +

    +

    Author: @armbian

    +

    Status: Stable

    + +

    Every day watchtower will pull the latest images and compare it to the one that was used to run the certain container. If it sees that the image has changed it will stop/remove containers and then restart it using the new image and the same docker run options that were used to start the container initially.

    + + +
    +

    Disable automating Docker container base images updating

    +

    Command: +

    Text Only
    armbian-config --cmd WTC002
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Armbian-Config/index.html b/611/User-Guide_Armbian-Config/index.html new file mode 100644 index 000000000..8d7f28256 --- /dev/null +++ b/611/User-Guide_Armbian-Config/index.html @@ -0,0 +1,1920 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Overview - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Armbian Config

    +
    flowchart LR
    +  A[armbian-config] -----> B["System"];
    +  A[armbian-config] -----> C["Network"];
    +  A[armbian-config] -----> D["Localistation"];
    +  A[armbian-config] -----> E["Software"];
    +  A[armbian-config] -----> F["Help"];
    +

    +

    Utility for configuring your board, adjusting services, and installing applications. It comes with Armbian by default.

    +

    To start the Armbian configuration utility, use the following command: +

    Text Only
    armbian-config
    +

    +

    Adding a new feature

    +

    Please check instructions.

    +

    Sources

    +

    armbian/configng

    +

    Installation on 3rd party Linux OS

    +

    This tool is tailored to works best with Armbian Linux but it has also been automatically tested on:

    +
      +
    • Debian Bookworm
    • +
    • Ubuntu Jammy
    • +
    • Ubuntu Noble
    • +
    +

    In theory it should work on any systemd APT based Linux distributions such as: Linux Mint, Elementary OS, Kali Linux, MX Linux, Parrot OS, Proxmox, Raspberry Pi OS, …

    +
    Text Only
    1
    +2
    +3
    +4
    +5
    +6
    +7
    wget -qO - https://apt.armbian.com/armbian.key | gpg --dearmor | \
    +sudo tee /usr/share/keyrings/armbian.gpg > /dev/null
    +echo "deb [signed-by=/usr/share/keyrings/armbian.gpg] \
    +https://github.armbian.com/configng stable main" | \
    +sudo tee /etc/apt/sources.list.d/armbian-config.list > /dev/null
    +sudo apt update
    +sudo apt -y install armbian-config
    +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Armbian-Software/Containers/index.html b/611/User-Guide_Armbian-Software/Containers/index.html new file mode 100644 index 000000000..f94ea858f --- /dev/null +++ b/611/User-Guide_Armbian-Software/Containers/index.html @@ -0,0 +1,2002 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Containers - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Docker containerization and KVM virtual machines

    +
    +

    Docker minimal

    + +

    Docker minimal

    + + +

    This operation will install Docker Minimal.

    +

    Command: +

    Text Only
    armbian-config --cmd CON001
    +

    +

    Author: @schwar3kat

    +

    Status: Stable

    + +

    What is Docker? Docker helps developers build, share, run, and verify applications anywhere - without tedious environment configuration or management.

    + + +
    +

    Docker engine

    +

    This operation will install Docker Engine.

    +

    Command: +

    Text Only
    armbian-config --cmd CON002
    +

    +

    Author: @schwar3kat

    +

    Status: Stable

    +
    +

    Docker remove

    +

    This operation will purge Docker.

    +

    Command: +

    Text Only
    armbian-config --cmd CON003
    +

    +

    Author: @schwar3kat

    +

    Status: Stable

    +
    +

    Docker purge with all images, containers, and volumes

    +

    This operation will delete all Docker images, containers, and volumes.

    +

    Command: +

    Text Only
    armbian-config --cmd CON004
    +

    +

    Author: @schwar3kat

    +

    Status: Stable

    +
    +

    Portainer container management platform

    + +

    Portainer container management platform

    + + + +

    Portainer simplifies your Docker container management via Portainer web interface. It enables faster deploy of the applications and it gives real time visibility.

    + + +

    Command: +

    Text Only
    armbian-config --cmd CON005
    +

    +

    Author: @armbian

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface is accessible via port 9002:

    +
      +
    • URL = http://<your.IP>:9002
    • +
    +
    +
    +
    + + +
    +

    Portainer remove

    +

    Command: +

    Text Only
    armbian-config --cmd CON006
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Portainer purge with with data folder

    +

    Command: +

    Text Only
    armbian-config --cmd CON007
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Armbian-Software/DNS/index.html b/611/User-Guide_Armbian-Software/DNS/index.html new file mode 100644 index 000000000..66c74c39a --- /dev/null +++ b/611/User-Guide_Armbian-Software/DNS/index.html @@ -0,0 +1,1945 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DNS blockers - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Network-wide ad blockers servers

    +
    +

    Pi-hole DNS ad blocker

    + +

    Pi-hole DNS ad blocker

    + + + +

    Pi-hole is a DNS sinkhole with web interface that will block ads for any device on your network.

    + + +

    Command: +

    Text Only
    armbian-config --cmd DNS001
    +

    +

    Author: @armbian

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface of Pi-hole can be accessed via:

    +
      +
    • URL = http://<your.IP>/admin
    • +
    • Password = ‘Set / adjust from armbian-config’
    • +
    +
    +
    +
    +
    +

    https://docs.pi-hole.net/

    + + +
    +

    Pi-hole remove

    +

    Command: +

    Text Only
    armbian-config --cmd DNS003
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Pi-hole change web admin password

    +

    Command: +

    Text Only
    armbian-config --cmd DNS002
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Pi-hole purge with data folder

    +

    Command: +

    Text Only
    armbian-config --cmd DNS004
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Armbian-Software/Database/index.html b/611/User-Guide_Armbian-Software/Database/index.html new file mode 100644 index 000000000..fd7c77896 --- /dev/null +++ b/611/User-Guide_Armbian-Software/Database/index.html @@ -0,0 +1,2022 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Database - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    SQL database servers and web interface managers

    +
    +

    Mariadb SQL database server

    + +

    Mariadb SQL database server

    + + + +

    Mariadb is one of the most popular database servers. Made by the original developers of MySQL.

    + + +

    Command: +

    Text Only
    armbian-config --cmd DAT001
    +

    +

    Author: @armbian

    +

    Status: Stable

    + +
    +
    +
    +

    Database access configuration is done at first install: +- create root password +- create database +- create normal user +- create password for normal user

    +
      +
    • Database host: <your.IP>
    • +
    +
    +
    +
      +
    • Install directory: /armbian/mariadb
    • +
    • Site configuration directory: /armbian/mariadb/config
    • +
    +
    +
    +
    Bash
    docker logs -f mariadb
    +
    +
    +
    +
    + + +
    +

    Mariadb remove

    +

    Command: +

    Text Only
    armbian-config --cmd DAT002
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Mariadb purge with data folder

    +

    Command: +

    Text Only
    armbian-config --cmd DAT003
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    phpMyAdmin web interface manager

    + +

    phpMyAdmin web interface manager

    + + + +

    Phpmyadmin is a free software tool written in PHP, intended to handle the administration of MySQL over the Web. phpMyAdmin supports a wide range of operations on MySQL and MariaDB.

    + + +

    Command: +

    Text Only
    armbian-config --cmd DAT005
    +

    +

    Author: @armbian

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface is accessible via port 8071:

    +
      +
    • URL: https://<your.IP>:8071
    • +
    • Server: IP from server you are connecting to. If you have installed MariaDB via this tool, then this is <your.IP>
    • +
    • Username: defined at SQL server install (MariaDb)
    • +
    • Password: defined at SQL server install (MariaDb)
    • +
    +
    +
    +
      +
    • Install directory: /armbian/phpmyadmin
    • +
    • Site configuration directory: /armbian/phpmyadmin/config
    • +
    +
    +
    +
    Bash
    docker logs -f phpmyadmin
    +
    +
    +
    +
    + + +
    +

    phpMyAdmin remove

    +

    Command: +

    Text Only
    armbian-config --cmd DAT006
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    phpMyAdmin purge with data folder

    +

    Command: +

    Text Only
    armbian-config --cmd DAT007
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Armbian-Software/Desktops/index.html b/611/User-Guide_Armbian-Software/Desktops/index.html new file mode 100644 index 000000000..81c36a813 --- /dev/null +++ b/611/User-Guide_Armbian-Software/Desktops/index.html @@ -0,0 +1,1874 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Desktops - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Desktop Environments

    +

    Status: Stable

    +
    +

    Improve application search speed

    +

    Command: +

    Text Only
    armbian-config --cmd Xapian
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Armbian-Software/DevTools/index.html b/611/User-Guide_Armbian-Software/DevTools/index.html new file mode 100644 index 000000000..baec13db5 --- /dev/null +++ b/611/User-Guide_Armbian-Software/DevTools/index.html @@ -0,0 +1,1889 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DevTools - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Applications and tools for development

    +
    +

    Install tools for cloning and managing repositories (git)

    +

    Command: +

    Text Only
    armbian-config --cmd DEV001
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Remove tools for cloning and managing repositories (git)

    +

    Command: +

    Text Only
    armbian-config --cmd DEV002
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Armbian-Software/Downloaders/index.html b/611/User-Guide_Armbian-Software/Downloaders/index.html new file mode 100644 index 000000000..f19556183 --- /dev/null +++ b/611/User-Guide_Armbian-Software/Downloaders/index.html @@ -0,0 +1,2838 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Downloaders - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Download apps for movies, TV shows, music and subtitles

    +
    +

    qBittorrent BitTorrent client

    + +

    qBittorrent BitTorrent client

    + + + +

    The Qbittorrent⁠ project aims to provide an open-source software alternative to µTorrent. qBittorrent is based on the Qt toolkit and libtorrent-rasterbar library.

    + + +

    This operation will install qBittorrent BitTorrent client

    +

    Command: +

    Text Only
    armbian-config --cmd DOW001
    +

    +

    Author: @armbian

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface is accessible via port 8090:

    +
      +
    • URL: https://<your.IP>:8090
    • +
    • Username/Password: admin / generate at first web interface login
    • +
    +
    +
    +
      +
    • Install directory: /armbian/qbittorrent
    • +
    • Site configuration directory: /armbian/qbittorrent/config
    • +
    • Download directory: /armbian/qbittorrent/downloads
    • +
    +
    +
    +
    Bash
    docker logs -f qbittorrent
    +
    +
    +
    +
    + + +
    +

    qBittorrent remove

    +

    This operation will remove qBittorrent BitTorrent client

    +

    Command: +

    Text Only
    armbian-config --cmd DOW002
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    qBittorrent purge with data folder

    +

    This operation will remove qBittorrent BitTorrent data folder

    +

    Command: +

    Text Only
    armbian-config --cmd DOW003
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Deluge BitTorrent client

    + +

    Deluge BitTorrent client

    + + + +

    Deluge⁠ is a lightweight, Free Software, cross-platform BitTorrent client.

    + + +

    This operation will install BitTorrent client

    +

    Command: +

    Text Only
    armbian-config --cmd DEL001
    +

    +

    Author: @armbian

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface is accessible via port 8112:

    +
      +
    • URL: https://<your.IP>:8112
    • +
    • Username/Password: default user/password of admin/deluge
    • +
    +
    +
    +
      +
    • Install directory: /armbian/deluge
    • +
    • Site configuration directory: /armbian/deluge/config
    • +
    • Download directory: /armbian/deluge/downloads
    • +
    +
    +
    +
    Bash
    docker logs -f deluge
    +
    +
    +
    +
    + + +
    +

    Deluge remove

    +

    This operation will remove Deluge BitTorrent client

    +

    Command: +

    Text Only
    armbian-config --cmd DEL002
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Deluge purge with data folder

    +

    This operation will remove Deluge BitTorrent client data folder

    +

    Command: +

    Text Only
    armbian-config --cmd DEL003
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Transmission BitTorrent client

    + +

    Transmission BitTorrent client

    + + + +

    Transmission⁠ is designed for easy, powerful use. Transmission has the features you want from a BitTorrent client: encryption, a web interface, peer exchange, magnet links, DHT, µTP, UPnP and NAT-PMP port forwarding, webseed support, watch directories, tracker editing, global and per-torrent speed limits, and more.

    + + +

    This operation will install Transmission BitTorrent client

    +

    Command: +

    Text Only
    armbian-config --cmd TRA001
    +

    +

    Author: @armbian

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface is accessible via port 9091:

    +
      +
    • URL: https://<your.IP>:9091
    • +
    • Username/Password: admin / generate at first web interface login
    • +
    +
    +
    +
      +
    • Install directory: /armbian/transmission
    • +
    • Site configuration directory: /armbian/transmission/config
    • +
    • Download directory: /armbian/transmission/downloads
    • +
    • Watch directory: /armbian/transmission/watch
    • +
    +
    +
    +
    Bash
    docker logs -f transmission
    +
    +
    +
    +
    + + +
    +

    Transmission remove

    +

    This operation will remove Transmission BitTorrent client

    +

    Command: +

    Text Only
    armbian-config --cmd TRA002
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Transmission purge with data folder

    +

    This operation will remove Transmission BitTorrent client data folder

    +

    Command: +

    Text Only
    armbian-config --cmd TRA003
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    SABnzbd newsgroup downloader

    + +

    SABnzbd newsgroup downloader

    + + + +

    Sabnzbd⁠ makes Usenet as simple and streamlined as possible by automating everything we can. All you have to do is add an .nzb. SABnzbd takes over from there, where it will be automatically downloaded, verified, repaired, extracted and filed away with zero human interaction.

    + + +

    This operation will install SABnzbd newsgroup downloader

    +

    Command: +

    Text Only
    armbian-config --cmd SABN01
    +

    +

    Author: @armbian

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface is accessible via port 8080:

    +
      +
    • URL: https://<your.IP>:8080
    • +
    • Username/Password: admin / generate at first web interface login
    • +
    +
    +
    +
      +
    • Install directory: /armbian/sabnzbd
    • +
    • Site configuration directory: /armbian/sabnzbd/config
    • +
    • Download directory: /armbian/sabnzbd/downloads
    • +
    • Incomplete downloads: /armbian/sabnzbd/incomplete
    • +
    +
    +
    +
    Bash
    docker logs -f sabnzbd
    +
    +
    +
    +
    + + +
    +

    SABnzbd remove

    +

    This operation will remove SABnzbd newsgroup downloader

    +

    Command: +

    Text Only
    armbian-config --cmd SABN02
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    SABnzbd purge with data folder

    +

    This operation will purge SABnzbd newsgroup data folder

    +

    Command: +

    Text Only
    armbian-config --cmd SABN03
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Medusa automatic downloader for TV shows

    + +

    Medusa is an automatic Video Library Manager for TV Shows. It watches for new episodes of your favorite shows, and when they are posted it does its magic.

    + + +

    This operation will install Medusa TV shows downloader

    +

    Command: +

    Text Only
    armbian-config --cmd MDS001
    +

    +

    Author: @armbian

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface is accessible via port 8081:

    +
      +
    • URL: https://<your.IP>:8081
    • +
    +
    +
    +
      +
    • Install directory: /armbian/medusa
    • +
    • Site configuration directory: /armbian/medusa/config
    • +
    • Download directory: /armbian/medusa/downloads
    • +
    • Download directory TV shows: /armbian/medusa/downloads/tv
    • +
    +
    +
    +
    Bash
    docker logs -f medusa
    +
    +
    +
    +
    + + +
    +

    Medusa TV shows downloader remove

    +

    This operation will remove Medusa TV shows downloader

    +

    Command: +

    Text Only
    armbian-config --cmd MDS002
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Medusa TV shows downloader purge

    +

    This operation will purge Medusa TV shows data folder

    +

    Command: +

    Text Only
    armbian-config --cmd MDS003
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Sonarr automatic downloader for TV shows

    + +

    Sonarr automatic downloader for TV shows

    + + + +

    Sonarr (formerly NZBdrone) is a PVR for usenet and bittorrent users. It can monitor multiple RSS feeds for new episodes of your favorite shows and will grab, sort and rename them. It can also be configured to automatically upgrade the quality of files already downloaded when a better quality format becomes available.

    + + +

    This operation will install Sonarr PVR for Usenet and BitTorrent

    +

    Command: +

    Text Only
    armbian-config --cmd SON001
    +

    +

    Author: @armbian

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface is accessible via port 8989:

    +
      +
    • URL: https://<your.IP>:8989
    • +
    +
    +
    +
      +
    • Install directory: /armbian/sonarr
    • +
    • Site configuration directory: /armbian/sonarr/config
    • +
    • Download directory: /armbian/sonarr/tvseries
    • +
    • Client download directory: /armbian/sonarr/client
    • +
    +
    +
    +
    Bash
    docker logs -f sonarr
    +
    +
    +
    +
    + + +
    +

    Sonarr remove

    +

    This operation will remove Sonarr PVR for Usenet and BitTorrent

    +

    Command: +

    Text Only
    armbian-config --cmd SON002
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Sonarr purge with data folder

    +

    This operation will purge Sonarr PVR for Usenet and BitTorrent purge data folder

    +

    Command: +

    Text Only
    armbian-config --cmd SON003
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Radarr automatic downloader for movies

    + +

    Radarr automatic downloader for movies

    + + + +

    Radarr - A fork of Sonarr to work with movies à la Couchpotato.

    + + +

    This operation will install Radarr movie collection manager

    +

    Command: +

    Text Only
    armbian-config --cmd RAD001
    +

    +

    Author: @armbian

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface is accessible via port 7878:

    +
      +
    • URL: https://<your.IP>:7878
    • +
    • Username/Password: admin / generate at first web interface login
    • +
    +
    +
    +
      +
    • Install directory: /armbian/radarr
    • +
    • Site configuration directory: /armbian/radarr/config
    • +
    • Download directory: /armbian/radarr/movies
    • +
    • Client download directory: /armbian/radarr/client
    • +
    +
    +
    +
    Bash
    docker logs -f radarr
    +
    +
    +
    +
    + + +
    +

    Radarr remove

    +

    This operation will remove Radarr movie collection manager

    +

    Command: +

    Text Only
    armbian-config --cmd RAD002
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Radarr purge with data folder

    +

    This operation will purge Radarr movie collection manager data folder

    +

    Command: +

    Text Only
    armbian-config --cmd RAD003
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Bazarr automatic subtitles downloader for Sonarr and Radarr

    + +

    Bazarr automatic subtitles downloader for Sonarr and Radarr

    + + + +

    Bazarr is a companion application to Sonarr and Radarr. It can manage and download subtitles based on your requirements. You define your preferences by TV show or movie and Bazarr takes care of everything for you.

    + + +

    This operation will install Bazarr subtitles manager for Sonarr and Radarr

    +

    Command: +

    Text Only
    armbian-config --cmd BAZ001
    +

    +

    Author: @armbian

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface is accessible via port 6767:

    +
      +
    • URL: https://<your.IP>:6767
    • +
    • Username/Password: admin / generate at first web interface login
    • +
    +
    +
    +
      +
    • Install directory: /armbian/bazarr
    • +
    • Site configuration directory: /armbian/bazarr/config
    • +
    • Download directory: /armbian/bazarr/movies /armbian/bazarr/tv
    • +
    +
    +
    +
    Bash
    docker logs -f bazarr
    +
    +
    +
    +
    + + +
    +

    Bazarr remove

    +

    This operation will remove Bazarr subtitles manager for Sonarr and Radarr

    +

    Command: +

    Text Only
    armbian-config --cmd BAZ002
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Bazarr purge with data folder

    +

    This operation will purge Bazarr subtitles manager with data folder

    +

    Command: +

    Text Only
    armbian-config --cmd BAZ003
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Lidarr automatic music downloader

    + +

    Lidarr automatic music downloader

    + + + +

    Lidarr is a music collection manager for Usenet and BitTorrent users. It can monitor multiple RSS feeds for new tracks from your favorite artists and will grab, sort and rename them. It can also be configured to automatically upgrade the quality of files already downloaded when a better quality format becomes available.

    + + +

    This operation will install Lidarr music collection manager for Usenet and BitTorrent users

    +

    Command: +

    Text Only
    armbian-config --cmd LID001
    +

    +

    Author: @armbian

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface is accessible via port 8686:

    +
      +
    • URL: https://<your.IP>:8686
    • +
    • Username/Password: admin / generate at first web interface login
    • +
    +
    +
    +
      +
    • Install directory: /armbian/lidarr
    • +
    • Site configuration directory: /armbian/lidarr/config
    • +
    • Download directory: /armbian/lidarr/downloads /armbian/lidarr/music
    • +
    +
    +
    +
    Bash
    docker logs -f lidarr
    +
    +
    +
    +
    + + +
    +

    Lidarr remove

    +

    This operation will remove Lidarr

    +

    Command: +

    Text Only
    armbian-config --cmd LID002
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Lidarr purge with data folder

    +

    This operation will purge Lidarr with data folder

    +

    Command: +

    Text Only
    armbian-config --cmd LID003
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Readarr automatic downloader for Ebooks

    + +

    Readarr automatic downloader for Ebooks

    + + + +

    Readarr - Book Manager and Automation (Sonarr for Ebooks)

    + + +

    This operation will install Readarr

    +

    Command: +

    Text Only
    armbian-config --cmd RDR001
    +

    +

    Author: @armbian

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface is accessible via port 8787:

    +
      +
    • URL: https://<your.IP>:8787
    • +
    • Username/Password: admin / generate at first web interface login
    • +
    +
    +
    +
      +
    • Install directory: /armbian/readarr
    • +
    • Site configuration directory: /armbian/readarr/config
    • +
    • Download directory: /armbian/readarr/books /armbian/readarr/client
    • +
    +
    +
    +
    Bash
    docker logs -f readarr
    +
    +
    +
    +
    + + +
    +

    Readarr remove

    +

    This operation will remove Readarr

    +

    Command: +

    Text Only
    armbian-config --cmd RDR002
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Readarr purge with data folder

    +

    This operation will purge Readarr with data folder

    +

    Command: +

    Text Only
    armbian-config --cmd RDR003
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Prowlarr index manager and proxy for PVR

    + +

    Prowlarr index manager and proxy for PVR

    + + + +

    Prowlarr is a indexer manager/proxy built on the popular arr .net/reactjs base stack to integrate with your various PVR apps. Prowlarr supports both Torrent Trackers and Usenet Indexers. It integrates seamlessly with Sonarr, Radarr, Lidarr, and Readarr offering complete management of your indexers with no per app Indexer setup required (we do it all).

    + + +

    This operation will install Prowlarr

    +

    Command: +

    Text Only
    armbian-config --cmd DOW025
    +

    +

    Author: @armbian

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface is accessible via port 9696:

    +
      +
    • URL: https://<your.IP>:9696
    • +
    • Username/Password: admin / generate at first web interface login
    • +
    +
    +
    +
      +
    • Install directory: /armbian/prowlarr
    • +
    • Site configuration directory: /armbian/prowlarr/config
    • +
    +
    +
    +
    Bash
    docker logs -f prowlarr
    +
    +
    +
    +
    + + +
    +

    Prowlarr remove

    +

    This operation will remove Prowlarr

    +

    Command: +

    Text Only
    armbian-config --cmd DOW026
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Prowlarr purge with data folder

    +

    This operation will purge Prowlarr with data folder

    +

    Command: +

    Text Only
    armbian-config --cmd DOW027
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Jellyseerr Jellyfin/Emby/Plex integration install

    + +

    Jellyseerr Jellyfin/Emby/Plex integration install

    + + + +

    Jellyseerr is a free and open source software application for managing requests for your media library. It is a fork of Overseerr built to bring support for Jellyfin & Emby media servers!

    + + +

    This operation will install Jellyseerr

    +

    Command: +

    Text Only
    armbian-config --cmd JEL001
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Jellyseerr remove

    +

    This operation will remove Jellyseerr

    +

    Command: +

    Text Only
    armbian-config --cmd JEL002
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Jellyseerr purge with data folder

    +

    This operation will purge Jellyseerr with data folder

    +

    Command: +

    Text Only
    armbian-config --cmd JEL003
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Armbian-Software/HomeAutomation/index.html b/611/User-Guide_Armbian-Software/HomeAutomation/index.html new file mode 100644 index 000000000..2fe879b86 --- /dev/null +++ b/611/User-Guide_Armbian-Software/HomeAutomation/index.html @@ -0,0 +1,2039 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Home Automation - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Home Automation for control home appliances

    +
    +

    openHAB empowering the smart home

    +

    This operation will install openHAB.

    +

    Command: +

    Text Only
    armbian-config --cmd HAB001
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    openHAB remove

    +

    This operation will purge openHAB.

    +

    Command: +

    Text Only
    armbian-config --cmd HAB002
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    openHAB purge with data folder

    +

    This operation will purge openHAB.

    +

    Command: +

    Text Only
    armbian-config --cmd HAB003
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Home Assistant open source home automation

    + +

    Home Assistant open source home automation

    + + + +

    Home Assistant is an open source smart home platform that allows you to connect your smart home devices like your TV, fan, cameras, thermostats, lights, and sensors. As a user, you can build intricate automation using Home Assistant’s user-friendly, unified web-based user interface.

    +

    Perfect to run on any single board computer with 4 cores and at least 512Mb of memory. Armbian installation is optimised to run from SD/eMMC media, but it is recommended to use SSD.

    +
    +
    +
    +

    The web interface is accessible via port 8123:

    +
      +
    • URL: https://<your.IP>:8123
    • +
    • Username/Password: Are set at first web interface login
    • +
    +
    +
    +

    Home Assistant on Armbian runs supervised in a Docker container. This secures same functionality as stock HAOS.

    +
      +
    • Config directory: /armbian/haos
    • +
    +
    +
    +
    + + +

    This operation will install Home Assistant.

    +

    Command: +

    Text Only
    armbian-config --cmd HAS001
    +

    +

    Author: @igorpecovnik

    +

    Status: Preview

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FunctionalityHAOSArmbian with HA
    Automations✔✔
    Dashboards✔✔
    Integrations✔✔
    Add-ons✔✔
    One-click updates✔✔
    Backups✔✔
    General purpose server❌✅
    Running on exotic hardware❌✅
    + + +
    +

    Home Assistant remove

    +

    This operation will remove Home Assistant.

    +

    Command: +

    Text Only
    armbian-config --cmd HAS002
    +

    +

    Author: @igorpecovnik

    +

    Status: Preview

    +
    +

    Home Assistant purge with data folder

    +

    This operation will purge Home Assistant.

    +

    Command: +

    Text Only
    armbian-config --cmd HAS003
    +

    +

    Author: @igorpecovnik

    +

    Status: Preview

    +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Armbian-Software/Management/index.html b/611/User-Guide_Armbian-Software/Management/index.html new file mode 100644 index 000000000..cc405f386 --- /dev/null +++ b/611/User-Guide_Armbian-Software/Management/index.html @@ -0,0 +1,1925 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Management - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Remote Management tools

    +
    +

    Cockpit web-based management tool

    + +

    Cockpit web-based management tool

    + + +

    Command: +

    Text Only
    armbian-config --cmd MAN001
    +

    +

    Author: @Tearran

    +

    Status: Stable

    + +

    Introducing Cockpit +Cockpit is a web-based graphical interface for servers, intended for everyone, especially those who are:

    +
      +
    • new to Linux +(including Windows admins)
    • +
    • familiar with Linux +and want an easy, graphical way to administer servers
    • +
    • expert admins +who mainly use other tools but want an overview on individual systems
    • +
    +

    Thanks to Cockpit intentionally using system APIs and commands, a whole team of admins can manage a system in the way they prefer, including the command line and utilities right alongside Cockpit.

    + + +
    +

    Webmin web-based management tool

    + +

    Webmin web-based management tool

    + + +

    Command: +

    Text Only
    armbian-config --cmd MAN005
    +

    +

    Author: @Tearran

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface is accessible via port 10000:

    +
      +
    • URL: https://<your.IP>:10000
    • +
    • Username/Password: your system login credentials
    • +
    +
    +
    +
    + + +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Armbian-Software/Media/index.html b/611/User-Guide_Armbian-Software/Media/index.html new file mode 100644 index 000000000..cdce13c5f --- /dev/null +++ b/611/User-Guide_Armbian-Software/Media/index.html @@ -0,0 +1,2261 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Media - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Media servers, organizers and editors

    +
    +

    Emby organizes video, music, live TV, and photos

    + +

    Emby organizes video, music, live TV, and photos

    + + + +

    Emby organizes video, music, live TV, and photos from personal media libraries and streams them to smart TVs, streaming boxes and mobile devices. This container is packaged as a standalone emby Media Server.

    + + +

    This operation will install Emby server.

    +

    Command: +

    Text Only
    armbian-config --cmd MED003
    +

    +

    Author: @schwar3kat

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface is accessible via port 8096:

    +
      +
    • URL: https://<your.IP>:8096
    • +
    +
    +
    +
      +
    • Install directory: /armbian/emby
    • +
    • Site configuration directory: /armbian/emby/config
    • +
    • Data directory: /armbian/emby/tvshows /armbian/emby/movies
    • +
    +
    +
    +
    Bash
    docker logs -f emby
    +
    +
    +
    +
    + + +
    +

    Emby server remove

    +

    This operation will remove Emby server

    +

    Command: +

    Text Only
    armbian-config --cmd MED004
    +

    +

    Author: @schwar3kat

    +

    Status: Stable

    +
    +

    Emby server purge with data folder

    +

    Command: +

    Text Only
    armbian-config --cmd MED005
    +

    +

    Author: @schwar3kat

    +

    Status: Stable

    +
    +

    Stirling PDF tools for viewing and editing PDF files

    + +

    Stirling PDF tools for viewing and editing PDF files

    + + + +

    Stirling-PDF is a robust, locally hosted web-based PDF manipulation tool using Docker. It enables you to carry out various operations on PDF files, including splitting, merging, converting, reorganizing, adding images, rotating, compressing, and more. This locally hosted web application has evolved to encompass a comprehensive set of features, addressing all your PDF requirements.

    + + +

    This operation will install Stirling-PDF tools.

    +

    Command: +

    Text Only
    armbian-config --cmd MED010
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface is accessible via port 8077:

    +
      +
    • URL: https://<your.IP>:8077
    • +
    +
    +
    +
      +
    • Install directory: /armbian/stirling
    • +
    +
    +
    +
    Bash
    docker logs -f stirling-pdf
    +
    +
    +
    +
    + + +
    +

    Stirling PDF remove

    +

    This operation will remove Stirling-PDF tools.

    +

    Command: +

    Text Only
    armbian-config --cmd MED011
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Stirling PDF purge with data folder

    +

    This operation will purge Stirling-PDF tools with data folder.

    +

    Command: +

    Text Only
    armbian-config --cmd MED012
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Syncthing continuous file synchronization

    + +

    Syncthing continuous file synchronization

    + + + +

    Syncthing replaces proprietary sync and cloud services with something open, trustworthy and decentralized. Your data is your data alone and you deserve to choose where it is stored, if it is shared with some third party and how it’s transmitted over the Internet.

    + + +

    Command: +

    Text Only
    armbian-config --cmd MED015
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface is accessible via port 8884:

    +
      +
    • URL: https://<your.IP>:8884
    • +
    • Username/Password: There is none, but it is highly suggested setting a password for this container. To do this go to Actions -> Settings -> set user/password for the webUI.
    • +
    +
    +
    +
      +
    • Install directory: /armbian/syncthing
    • +
    • Site configuration directory: /armbian/syncthing/config
    • +
    • Data directory: /armbian/syncthing/data1 /armbian/syncthing/data2
    • +
    +
    +
    +
    Bash
    docker logs -f syncthing
    +
    +
    +
    +
    + + +
    +

    Syncthing remove

    +

    Command: +

    Text Only
    armbian-config --cmd MED016
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Syncthing purge with data folder

    +

    Command: +

    Text Only
    armbian-config --cmd MED017
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Nextcloud content collaboration platform

    + +

    Nextcloud content collaboration platform

    + + + +

    Nextcloud gives you access to all your files wherever you are. +
    +Where are your photos and documents? With Nextcloud you pick a server of your choice, at home, in a data center or at a provider. And that is where your files will be. Nextcloud runs on that server, protecting your data and giving you access from your desktop or mobile devices. Through Nextcloud you also access, sync and share your existing data on that FTP drive at the office, a Dropbox or a NAS you have at home.

    + + +

    Command: +

    Text Only
    armbian-config --cmd MED020
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface is accessible via port 443:

    +
      +
    • URL: https://<your.IP>:443
    • +
    • Username/Password: admin / generate at first web interface login
    • +
    +
    +
    +
      +
    • Install directory: /armbian/nextcloud
    • +
    • Site configuration directory: /armbian/nextcloud/config
    • +
    • Data directory: /armbian/nextcloud/data
    • +
    +
    +
    +
    Bash
    docker logs -f nextcloud
    +
    +
    +
    +
    + + +
    +

    Nextcloud remove

    +

    Command: +

    Text Only
    armbian-config --cmd MED021
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Nextcloud purge with data folder

    +

    Command: +

    Text Only
    armbian-config --cmd MED022
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Owncloud share files and folders, easy and secure

    +

    Command: +

    Text Only
    armbian-config --cmd MED025
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Owncloud remove

    +

    Command: +

    Text Only
    armbian-config --cmd MED026
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Owncloud purge with data folder

    + +

    ownCloud is a free and open-source software project for content collaboration and sharing and syncing of files in distributed and federated enterprise scenarios.

    + + +

    Command: +

    Text Only
    armbian-config --cmd MED027
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface is accessible via port 7787:

    +
      +
    • URL: http://<your.IP>:7787
    • +
    • Username/Password: admin / admin
    • +
    +
    +
    +
      +
    • Install directory: /armbian/owncloud
    • +
    • Site configuration directory: /armbian/owncloud/config
    • +
    • Data directory: /armbian/owncloud/data
    • +
    +
    +
    +
    Bash
    docker logs -f owncloud
    +
    +
    +
    +
    + + +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Armbian-Software/Monitoring/index.html b/611/User-Guide_Armbian-Software/Monitoring/index.html new file mode 100644 index 000000000..87b49c096 --- /dev/null +++ b/611/User-Guide_Armbian-Software/Monitoring/index.html @@ -0,0 +1,2076 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Monitoring - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Real-time monitoring, collecting metrics, up-time status

    +
    +

    Uptime Kuma self-hosted monitoring tool

    +

    This operation will install Uptime Kuma

    +

    Command: +

    Text Only
    armbian-config --cmd MON001
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface is accessible via port 3001:

    +
      +
    • URL: https://<your.IP>:3001
    • +
    • Username/Password: Are set at first web interface login
    • +
    +
    +
    +
    +
    +Uptime Kuma features +
      +
    • Monitoring uptime for HTTP(s) / TCP / HTTP(s) Keyword / HTTP(s) Json Query / Ping / DNS Record / Push / Steam Game Server / Docker Containers
    • +
    • Fancy, Reactive, Fast UI/UX
    • +
    • Notifications via Telegram, Discord, Gotify, Slack, Pushover, Email (SMTP), and 90+ notification services, click here for the full list
    • +
    • 20-second intervals
    • +
    • Multi Languages
    • +
    • Multiple status pages
    • +
    • Map status pages to specific domains
    • +
    • Ping chart
    • +
    • Certificate info
    • +
    • Proxy support
    • +
    • 2FA support
    • +
    +
    + + +
    +

    Uptime Kuma remove

    +

    This operation will remove Uptime Kuma

    +

    Command: +

    Text Only
    armbian-config --cmd MON002
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Uptime Kuma purge with data folder

    +

    This operation will remove Uptime Kuma with data folder

    +

    Command: +

    Text Only
    armbian-config --cmd MON003
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Netdata - monitoring real-time metrics

    + +

    Netdata - monitoring real-time metrics

    + + + +

    Netdata is a partially open source tool designed to collect real-time metrics, such as CPU usage, disk activity, bandwidth usage, website visits, etc., and then display them in live, easy-to-interpret charts.

    + + +

    This operation will install Netdata

    +

    Command: +

    Text Only
    armbian-config --cmd MON005
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Netdata remove

    +

    This operation will remove Netdata

    +

    Command: +

    Text Only
    armbian-config --cmd MON006
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Netdata purge with data folder

    +

    This operation will purge Netdata with data folder

    +

    Command: +

    Text Only
    armbian-config --cmd MON007
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    +

    Grafana data analytics

    + +

    Grafana data analytics

    + + + +

    Grafana is a multi-platform open source analytics and interactive visualization web application. It can produce charts, graphs, and alerts for the web when connected to supported data sources.

    + + +

    Command: +

    Text Only
    armbian-config --cmd GRA001
    +

    +

    Author: @armbian

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface is accessible via port 3000:

    +
      +
    • URL: https://<your.IP>:3000
    • +
    +
    +
    +
      +
    • Install directory: /armbian/grafana
    • +
    +
    +
    +
    Bash
    docker logs -f grafana
    +
    +
    +
    +
    + + +
    +

    Grafana remove

    +

    Command: +

    Text Only
    armbian-config --cmd GRA002
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    Grafana purge with data folder

    +

    This operation will purge Grafana with data folder

    +

    Command: +

    Text Only
    armbian-config --cmd GRA003
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Armbian-Software/Music/index.html b/611/User-Guide_Armbian-Software/Music/index.html new file mode 100644 index 000000000..8e8f88522 --- /dev/null +++ b/611/User-Guide_Armbian-Software/Music/index.html @@ -0,0 +1,1905 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Music - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Music servers and streamers

    +
    + +

    Command: +

    Text Only
    armbian-config --cmd NAV001
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    + +

    Command: +

    Text Only
    armbian-config --cmd NAV002
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    + +

    Command: +

    Text Only
    armbian-config --cmd NAV003
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Armbian-Software/Netconfig/index.html b/611/User-Guide_Armbian-Software/Netconfig/index.html new file mode 100644 index 000000000..e4a311d8f --- /dev/null +++ b/611/User-Guide_Armbian-Software/Netconfig/index.html @@ -0,0 +1,1985 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Netconfig - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Console network tools for measuring load and bandwidth

    +
    +

    nload -realtime console network usage monitor

    +

    Command: +

    Text Only
    armbian-config --cmd NET001
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    nload - remove

    +

    Command: +

    Text Only
    armbian-config --cmd NET002
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    iperf3 bandwidth measuring tool

    +

    Command: +

    Text Only
    armbian-config --cmd NET003
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    iperf3 remove

    +

    Command: +

    Text Only
    armbian-config --cmd NET004
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    iptraf-ng IP LAN monitor

    +

    Command: +

    Text Only
    armbian-config --cmd NET005
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    iptraf-ng remove

    +

    Command: +

    Text Only
    armbian-config --cmd NET006
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    avahi-daemon hostname broadcast via mDNS

    +

    Command: +

    Text Only
    armbian-config --cmd NET007
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    avahi-daemon remove

    +

    Command: +

    Text Only
    armbian-config --cmd NET008
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Armbian-Software/Printing/index.html b/611/User-Guide_Armbian-Software/Printing/index.html new file mode 100644 index 000000000..d26b624d6 --- /dev/null +++ b/611/User-Guide_Armbian-Software/Printing/index.html @@ -0,0 +1,1938 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Printing - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Tools for printing and 3D printing

    +
    +

    OctoPrint web-based 3D printers management tool

    + +

    OctoPrint web-based 3D printers management tool

    + + + +

    OctoPrint is an open source 3D printer controller application, which provides a web interface for the connected printers. It displays printers status and key parameters and allows user to schedule prints and remotely control the printer.

    + + +

    This operation will install OctoPrint

    +

    Command: +

    Text Only
    armbian-config --cmd OCT001
    +

    +

    Author: @armbian

    +

    Status: Stable

    + +
    +
    +
    +

    The web interface is accessible via port 7981:

    +
      +
    • URL: https://<your.IP>:7981
    • +
    +
    +
    +
      +
    • Install directory: /armbian/octoprint
    • +
    +
    +
    +
    Bash
    docker logs -f octoprint
    +
    +
    +
    +
    + + +
    +

    OctoPrint remove

    +

    This operation will remove OctoPrint

    +

    Command: +

    Text Only
    armbian-config --cmd OCT002
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    OctoPrint purge with data folder

    +

    This operation will purge OctoPrint with data folder

    +

    Command: +

    Text Only
    armbian-config --cmd OCT003
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Armbian-Software/WebHosting/index.html b/611/User-Guide_Armbian-Software/WebHosting/index.html new file mode 100644 index 000000000..f5f3641d5 --- /dev/null +++ b/611/User-Guide_Armbian-Software/WebHosting/index.html @@ -0,0 +1,1954 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Web hosting - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Web server, LEMP, reverse proxy, Let’s Encrypt SSL

    +

    Status: Stable

    +
    +

    SWAG reverse proxy

    + +

    SWAG reverse proxy

    + + + +

    SWAG - Secure Web Application Gateway sets up an Nginx webserver and reverse proxy with php support and a built-in certbot client that automates free SSL server certificate generation and renewal processes (Let’s Encrypt). It also contains fail2ban for intrusion prevention.

    +

    After entering required information, your server will have auto updating SSL secured website! To this website you can attach several services, for example: https://my.server.com/netdata will run Netdata instance.

    +
    +
    +
    +
      +
    • this computer port 80 and 443 must be open to the internet
    • +
    • your domain name (myserver.mydomain.com) DNS server should point to your router WAN address
    • +
    • make sure to set additional .htpasswd username and password as you don’t want to expose your services without password
    • +
    +
    +
    +
      +
    • Config directory: /armbian/swag/config/
    • +
    • Website root folder: /armbian/swag/config/www/
    • +
    • Reverse proxy configuration samples: /armbian/swag/config/nginx/proxy-confs/
    • +
    +
    +
    + +
    +
    +
    + + +

    Command: +

    Text Only
    armbian-config --cmd SWAG01
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    SWAG reverse proxy .htpasswd set

    +

    Command: +

    Text Only
    armbian-config --cmd SWAG02
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    SWAG remove

    +

    Command: +

    Text Only
    armbian-config --cmd SWAG03
    +

    +

    Author: @armbian

    +

    Status: Stable

    +
    +

    SWAG purge with data folder

    +

    Command: +

    Text Only
    armbian-config --cmd SWAG04
    +

    +

    Author: @igorpecovnik

    +

    Status: Stable

    +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Armbian-Software/index.html b/611/User-Guide_Armbian-Software/index.html new file mode 100644 index 000000000..22cb8f49c --- /dev/null +++ b/611/User-Guide_Armbian-Software/index.html @@ -0,0 +1,1880 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Overview - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Armbian Software

    +
    flowchart LR
    +  A[Software] ----> B["Containerlization"];
    +  A[Software] ----> C["Desktops"];
    +  A[Software] -----> D["DNS blockers"];
    +  A[Software] -----> E["Home Automation"];
    +  A[Software] ------> F["Monitoring"];
    +  A[Software] ------> G["Development"];
    +  A[Software] ------> J["Network tools"];
    +  A[Software] ----------> H["Remote Management tools"];
    +  A[Software] ----------> I["Media Servers"];
    +

    To start the Armbian software section, use the following command and choose software section: +

    Text Only
    armbian-config
    +

    +

    Adding a new feature

    +

    Please check instructions.

    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Armbian_overlays/index.html b/611/User-Guide_Armbian_overlays/index.html new file mode 100644 index 000000000..c795d0a5b --- /dev/null +++ b/611/User-Guide_Armbian_overlays/index.html @@ -0,0 +1,2176 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Device tree overlays - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Device Tree overlays

    +

    Most in-circuit and GPIO based interfaces (SPI, I2C, I2S, UART, …) don’t have a mechanism for detecting and identifying devices connected to the bus, +so Linux kernel has to be told explicitly about the device and its configuration details.

    +

    While Device Tree is a way of describing hardware configuration to the kernel, Device Tree overlays are a way for modifying the DT +in order to provide the kernel and kernel drivers with details about external devices or to activate interfaces disabled by default.

    +

    Note: from the Linux kernel maintainer perspective all unused in-circuit type interfaces that use GPIO pins should be disabled by default and all pins on pin headers or soldering pads will be configured as standard GPIOs.

    +

    Note: from the Linux kernel maintainer perspective all dedicated interfaces like USB, Ethernet or analog audio that are wired to soldering pads or a pin headers instead of specialized sockets (like USB socket, Ethernet socket or 3.5mm jack) will be left disabled by default.

    +

    Armbian specific notes

    +
      +
    • DT overlays are a Work-in-Progress (WIP) feature, present only in certain images.
    • +
    • Please note that different SoCs will have different sets of available overlays.
    • +
    +

    Quick start

    +
      +
    1. Check the README.<soc-id>-overlays in /boot/dtb/overlay/ (32-bit SoCs) or /boot/dtb/allwinner/overlay/ (64-bit SoCs) for a list of provided overlays, their required and optional parameters
    2. +
    3. Add names of overlays you want to activate to overlays= line in /boot/armbianEnv.txt, separated with spaces
    4. +
    5. Add required parameters with their values to /boot/armbianEnv.txt, one per line
    6. +
    7. Add optional parameters with their values to /boot/armbianEnv.txt if you want to change the default value, one per line
    8. +
    9. If you didn’t find the required overlay or want to change one of provided overlays, refer to “Using custom overlays” section
    10. +
    11. Reboot
    12. +
    +

    Using custom overlays

    +
      +
    1. Check here for some example overlays
    2. +
    3. Copy or create your overlay file (with .dts extension) on the device
    4. +
    5. Change I2C or SPI bus number, GPIO and pinctrl pins, compatible string to match your SoC if necessary
    6. +
    7. Compile and activate the overlay by running armbian-add-overlay <overlay_file.dts> as root, i.e. sudo armbian-add-overlay sht15.dts
    8. +
    9. Reboot
    10. +
    +

    armbianEnv.txt entries reference

    +
      +
    • overlay_prefix - prefix for the DT and overlay file names, set at OS image creation time
    • +
    • overlays - list of overlays to activate from kernel directory
    • +
    • user_overlays - list of overlays to activate from /boot/overlay-user/ directory
    • +
    • param_* - overlay parameters
    • +
    +

    Kernel provided vs user provided overlays

    +

    Overlays can be loaded from 2 locations:

    +
      +
    • /boot/dtb/overlay/ (/boot/dtb/allwinner/overlay/ for 64-bit SoCs) - kernel provided overlays
    • +
    • /boot/overlay-user/ - user provided overlays
    • +
    +

    Main differences between these locations:

    +
      +
    • Kernel provided overlays are updated with the kernel packages, any changes to this directory (including new files) will be lost on kernel upgrade
    • +
    • Kernel provided directory may contain overlays for different SoCs, so overlay file name pattern will be <prefix>-<name>, for example sun8i-h3-i2c0.dtbo, where sun8i-h3 is the prefix and i2c0 is the name
    • +
    • Kernel provided overlays are activated by the overlay name (i.e. i2c0), and the prefix is set at OS image creation time
    • +
    • User provided overlays directory is empty by default and is meant for storing and using user created overlays that are not present in the kernel packages or modified stock overlays
    • +
    • User provided overlays are activated by the file name (excluding the extension), i.e. for file adafruit13m.dtbo overlay name would be adafruit13m
    • +
    +

    Activation

    +

    DT overlays are activated by editing u-boot environment file /boot/armbianEnv.txt

    +
      +
    • Kernel provided overlays are activated by adding a name to the overlays variable
    • +
    • User provided overlays are activated by adding a name to the user_overlays variable
    • +
    • No more than one overlays line and one user_overlays line can be present in the environment file
    • +
    • Multiple names should be separated by space
    • +
    • If activated overlays have parameters marked as “Required”, those parameters have to be set to proper values
    • +
    • Reboot is required for any changes to take effect
    • +
    +

    Overlay parameters

    +

    Some overlays have additional parameters that can be set.

    +

    Parameters marked as “Required” have to be set if overlay with these parameters is activated, other parameters are not mandatory if default value is suitable.

    +

    Parameters are set by adding their name and value to /boot/armbianEnv.txt, each parameter should be added on a new line.

    +

    Please refer to README.<SoC_prefix>-overlays files in /boot/dtb/overlay/ (/boot/dtb/allwinner/overlay/ for 64-bit SoCs) directory for supported parameters, i.e. README.sun8i-h3-overlays for H3 based boards.

    +

    Parameters of type pin require special format:

    +
      +
    • Value consists of a letter P, a letter that signifies the pin bank and a number of the pin in the bank
    • +
    • Letters should be upper case
    • +
    • Numbers should not contain leading zeros
    • +
    • Examples: good - PA9, PG12; bad - pa2, PG08
    • +
    +

    Overlay bus selection

    +

    SoCs may contain multiple bus controllers of the same type, i.e. Allwinner H3 contains 2 SPI controllers and Allwinner A20 contains 4 SPI controllers.

    +

    Please refer to your board documentation and schematic to determine what pins are wired to the pin headers and thus what bus number should be used in each case.

    +

    Overlay pinmux conflicts

    +

    Some controllers may share the SoC pins in some configurations. For example on Allwinner H3 UART 3 and SPI 1 use the same pins - PA13, PA14, PA15, PA16. +In this case activating both UART 3 and SPI 1 would result in a conflict, and on practice only one interface (either SPI or UART) will be accessible on these pins.

    +

    Please check the SoC specific README, board schematic, SoC datasheet or other documentation if you are unsure about possible conflicts if activating multiple overlays for the controllers that use shared (muxed) pins.

    +

    Overlay device endpoint conflicts

    +

    Overlays for devices that use addresses or similar mechanisms (i.e. SPI chip selects) can’t be activated simultaneously if addresses (chip selects) are identical.

    +

    For example A20 SPI controller 1 has only one hardware chip select, so spi-spidev and spi-jedec-nor overlays cannot be activated both if they would use the same bus number and chip select.

    +

    Overlay compatibility

    +

    Device Tree overlays for different platforms and SoCs are not directly compatible. +This, for example, means that overlays for H3 may need some changes to work on A20, and that Raspberry Pi overlays will need adjustments in order to be used on Allwinner based boards.

    +

    Rework may include changing labels, references (phandles) and pinconf bindings.

    +

    Notes regarding SPI and I2S overlays

    +

    Activating a device on SPI or I2S bus may require more than one overlay. +In case a bus overlay like spi0 or i2s0 exist for the target SoC they need to be activated in addition to a slave device overlay (provided or custom/user-made). +Please note that these overlays (spi0, i2s0) do not enable any slave devices (like spidev or I2S codec).
    +In some cases it might be necessary to change param_spidev_spi_bus to 1.

    +

    Debugging

    +

    As overlays and overlay parameters are applied by the u-boot, it is impossible to get any debugging information (such as error messages) from the OS.

    +

    Serial console on UART 0 is required to debug DT overlay related problems.

    +

    Example /boot/armbianEnv.txt contents:

    +
    Text Only
     1
    + 2
    + 3
    + 4
    + 5
    + 6
    + 7
    + 8
    + 9
    +10
    verbosity=1
    +console=serial
    +overlay_prefix=sun8i-h3
    +rootdev=UUID=bd0ded76-1188-4b52-a20a-64f326c1f193
    +rootfstype=ext4
    +overlays=w1-gpio uart1 i2c0 spi-spidev
    +param_w1_pin=PA20
    +param_w1_pin_int_pullup=1
    +param_uart1_rtscts=1
    +param_spidev_spi_bus=0
    +
    +

    Example of serial console log when using several overlays:

    +
    Text Only
     1
    + 2
    + 3
    + 4
    + 5
    + 6
    + 7
    + 8
    + 9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    ## Executing script at 43100000
    +U-boot loaded from SD
    +Boot script loaded from mmc
    +265 bytes read in 182 ms (1000 Bytes/s)
    +5074230 bytes read in 532 ms (9.1 MiB/s)
    +5702664 bytes read in 579 ms (9.4 MiB/s)
    +Found mainline kernel configuration
    +32724 bytes read in 269 ms (118.2 KiB/s)
    +882 bytes read in 277 ms (2.9 KiB/s)
    +Applying kernel provided DT overlay sun8i-h3-w1-gpio.dtbo
    +506 bytes read in 326 ms (1000 Bytes/s)
    +Applying kernel provided DT overlay sun8i-h3-uart1.dtbo
    +374 bytes read in 377 ms (0 Bytes/s)
    +Applying kernel provided DT overlay sun8i-h3-i2c0.dtbo
    +788 bytes read in 347 ms (2 KiB/s)
    +Applying kernel provided DT overlay sun8i-h3-spi-spidev.dtbo
    +4327 bytes read in 268 ms (15.6 KiB/s)
    +Applying kernel provided DT fixup script (sun8i-h3-fixup.scr)
    +## Executing script at 44000000
    +tmp_bank=A
    +tmp_pin=20
    +## Loading init Ramdisk from Legacy Image at 43300000 ...
    +   Image Name:   uInitrd
    +   Image Type:   ARM Linux RAMDisk Image (gzip compressed)
    +   Data Size:    5074166 Bytes = 4.8 MiB
    +   Load Address: 00000000
    +   Entry Point:  00000000
    +   Verifying Checksum ... OK
    +## Flattened Device Tree blob at 43000000
    +   Booting using the fdt blob at 0x43000000
    +   reserving fdt memory region: addr=43000000 size=9000
    +   Loading Ramdisk to 49b29000, end 49fffcf6 ... OK
    +   Loading Device Tree to 49b1d000, end 49b28fff ... OK
    +
    +Starting kernel ...
    +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Autoconfig/index.html b/611/User-Guide_Autoconfig/index.html new file mode 100644 index 000000000..1f8cfca57 --- /dev/null +++ b/611/User-Guide_Autoconfig/index.html @@ -0,0 +1,2120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Firstboot config - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Automatic first boot configuration

    +

    Reading presets from local config

    +

    It is possible to configure your device automatically at first boot. Settings like: root password, IP address, connecting to wireless.

    +

    After flashing an image to boot media, mount it and add a file containing your config to /root/.not_logged_in_yet

    +
    +Tip +

    You may also mount the image and edit it prior to flashing, if this is preferable.

    +
    +

    Loading a remote config

    +

    It is also possible to load this config file from a remote server, as above, however the only directive you should include is:

    +
    /root/.not_logged_in_yet
    PRESET_CONFIGURATION="http://path/to/config/file"
    +
    +

    Configuration directives

    +
      +
    • The directives in this file are specified using key="value" format.
    • +
    • To ask for a value interactively, leave it unset or comment out the directive.
    • +
    • For fully-unattended setup, specify all values.
    • +
    +
    +

    Caution

    +

    No validation of this network config is performed, wrong settings will lead to broken network.
    +Armbian supports netplan.io, this is the preferred config method.
    +See netplan guides for various example configurations.
    +Netplan config is stored in /etc/netplan/.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Configuration directive[default] | optionDescription:
    PRESET_CONFIGURATIONhttp://path/to/config/fileSee Loading a remote config
    PRESET_NET_CHANGE_DEFAULTS[0] | 1Change default network settings
    if unset, no network changes will be applied
    PRESET_NET_ETHERNET_ENABLED0 | 1Enable Ethernet, ignored if WiFi enabled
    PRESET_NET_WIFI_ENABLED0 | 1Enable WiFi, takes priority over Ethernet
    PRESET_NET_WIFI_SSIDMySSIDWiFi SSID
    PRESET_NET_WIFI_KEYMyWPA-PSKWiFi Pre-Shared Key (Password), stored in plaintext
    PRESET_NET_WIFI_COUNTRYCODECCCountry code, required for WiFi
    e.g. GB, US, DE; see Wikipedia/ISO_3166
    PRESET_CONNECT_WIRELESSY | nSet to Y for interactive mode, n uses values from file
    PRESET_NET_USE_STATIC[0] | 1Use the static IP provided, DHCP is the default
    Leaving any value unset will result in a broken config
    PRESET_NET_STATIC_IPxxx.xxx.xxx.xxxStatic IPv4 address, dotted decimal notation
    PRESET_NET_STATIC_MASKxxx.xxx.xxx.xxxSubnet mask, typically 255.255.255.0
    PRESET_NET_STATIC_GATEWAYxxx.xxx.xxx.xxxDefault gateway address
    PRESET_NET_STATIC_DNSx.x.x.x x.x.x.xDNS Servers to use, separated by a space. If unsure:
    CloudFlare is 1.1.1.1 1.0.0.1
    Google is 8.8.8.8 8.8.4.4
    SET_LANG_BASED_ON_LOCATIONY | n“Set user language based on your location?”
    PRESET_LOCALElocaleLocale e.g. en_GB.UTF-8, de_DE.UTF-8, zh_TW.UTF-8
    PRESET_TIMEZONEtimezoneTimezone e.g. Etc/UTC,
    PRESET_ROOT_PASSWORD[1234] | passwordPreset root password
    Stored in plaintext, SSH keys are safer!
    PRESET_ROOT_KEYhttps://path/to/key.fileFetches public key from specified URL for root user
    PRESET_USER_NAMEusernameUsername to create
    PRESET_USER_PASSWORDpasswordPreset created user password
    Stored in plaintext, SSH keys are safer!
    PRESET_USER_KEYhttps://path/to/key.fileFetches public key from specified URL for created user
    PRESET_DEFAULT_REALNAMEReal NameRealName to use for created user
    PRESET_USER_SHELLshellCurrently only bash (default) or zsh (armbian-zsh) supported
    +

    Sample config file

    +

    The following is an example configuration, it may be used as a template

    +
    /root/.not_logged_in_yet
     1
    + 2
    + 3
    + 4
    + 5
    + 6
    + 7
    + 8
    + 9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    #/root/.not_logged_in_yet
    +# Network Settings
    +PRESET_NET_CHANGE_DEFAULTS="1"
    +## Ethernet
    +PRESET_NET_ETHERNET_ENABLED="1"     #   Ignored due to WiFi
    +## WiFi
    +PRESET_NET_WIFI_ENABLED="1"
    +PRESET_NET_WIFI_SSID="MySSID"
    +PRESET_NET_WIFI_KEY="MyWiFiKEY"
    +PRESET_NET_WIFI_COUNTRYCODE="GB"
    +PRESET_CONNECT_WIRELESS="n"
    +## Static IP
    +PRESET_NET_USE_STATIC="1"
    +PRESET_NET_STATIC_IP="192.168.0.100"
    +PRESET_NET_STATIC_MASK="255.255.255.0"
    +PRESET_NET_STATIC_GATEWAY="192.168.0.1"
    +PRESET_NET_STATIC_DNS="8.8.8.8 8.8.4.4"
    +
    +# System
    +SET_LANG_BASED_ON_LOCATION="y"
    +PRESET_LOCALE="en_US.UTF-8"
    +PRESET_TIMEZONE="Etc/UTC"
    +
    +# Root
    +PRESET_ROOT_PASSWORD="RootPassword"
    +PRESET_ROOT_KEY=""
    +
    +# User
    +PRESET_USER_NAME="armbian"
    +PRESET_USER_PASSWORD="UserPassword"
    +PRESET_USER_KEY=""
    +PRESET_DEFAULT_REALNAME="Armbian user"
    +PRESET_USER_SHELL="bash"
    +
    +
    +Tip +

    If you want to use first run automatic configuration at build time, check this GitHub pull request.

    +

    tl;dr;

    +
      +
    1. Copy the template with cp extensions/preset-firstrun.sh userpatches/extensions/
    2. +
    3. Edit the template userpatches/extensions/preset-firstrun.sh according to your situation
    4. +
    5. Build your Armbian image using the additional parameter ENABLE_EXTENSIONS=preset-firstrun
    6. +
    +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Basic-Troubleshooting/index.html b/611/User-Guide_Basic-Troubleshooting/index.html new file mode 100644 index 000000000..8e2369f06 --- /dev/null +++ b/611/User-Guide_Basic-Troubleshooting/index.html @@ -0,0 +1,2137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Basic Troubleshooting - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Hardware troubleshooting guide

    +

    First aid video guide:

    + + +

    If you are experiencing at least one of these problems:

    +
      +
    • board does not boot
    • +
    • board freezes, crashes or reboots randomly or when connecting USB devices
    • +
    • plugged in USB devices are not detected (not listed in lsusb output)
    • +
    • error changing the root password at first boot (Authentication token manipulation error)
    • +
    • error installing or updating packages due to read-only file system
    • +
    +

    and you are using a stable Armbian image, then most likely you have one of two common problems - powering issue or SD card issue.

    +

    Note that

    +
      +
    • “I know that my power supply is good”, “it worked yesterday”, “it works with a different device”, etc. are not objective reasons to skip powering related diagnostics
    • +
    • “I know that my SD card is good”, “it worked yesterday”, “it works with a different device”, etc. are not objective reasons to skip storage related diagnostics
    • +
    • undervoltage can cause symptoms related to SD card problems such as filesystem corruptions and data loss, so powering has to be checked first
    • +
    +

    Powering notes

    +
      +
    • Most boards, even ones fitted with PMIC (power management integrated circuit) do not have any measures to react to undervoltage that could prevent instability
    • +
    • It does not matter what voltage your power supply outputs, it matters what voltage will reach the onboard voltage regulators
    • +
    • Peak power consumption of popular boards can vary from 0.9A at 5V (H3 based Orange Pi PC) to 1.7A at 5V (RK3288 based Tinkerboard), both without any attached peripherials like USB devices
    • +
    • Due to the Ohm’s law voltage drop due to cable and connector resistance will be proportional to the electric current, so most of the time problems will be experienced at current spikes caused by CPU load or peripherials like spinning up HDDs
    • +
    +

    Power supply

    +
      +
    • Cheap phone chargers may not provide the current listed on their label, especially for long time periods
    • +
    • Some cheap phone chargers don’t have proper feedback based stabilization, so output voltage may change depending on load
    • +
    • Power supplies will degrade over time (especially when working 24/7)
    • +
    • Some problems like degraded output filtering capacitors cannot be diagnosed even with a multimeter because of the non-linear voltage form
    • +
    +

    Cable

    +
      +
    • The longer and thinner the cable - the higher its resistance - the greater the voltage drop will be under load
    • +
    • Even thick looking cable can have thin wires inside, so do not trust the outside cable diameter
    • +
    +

    Connector

    +
      +
    • MicroUSB connector is rated for the maximum current of 1.8A, but even this number cannot be guaranteed. Trying to pass larger current (even momentarily) may result in a voltage dropping below USB specifications
    • +
    • Most of the boards can also be powered through GPIO pins. This can be used to bypass the microUSB connector and thus to improve stability
    • +
    +

    SD card notes

    +
      +
    • A SD card is a complex storage device with an embedded controller that processes read, erase and write operations, wear leveling, error and corruption detection, but it does not provide any diagnostic protocols like S.M.A.R.T.
    • +
    • SD cards will degrade over time and may fail in the end in different ways - become completely or partially read-only or cause a silent data corruption
    • +
    +

    SD card brand

    +
      +
    • Based on current prices and performance tests done by Armbian users Samsung Evo, Samsung Evo Plus and Sandisk Ultra cards are recommended
    • +
    • Other good alternatives may be added to this page in the future
    • +
    +

    SD card size and speed class

    +
      +
    • SD card speed class and size does not influence the reliability directly, but larger size means larger amount of lifetime data written, even if you are using 10-20% of the cards space
    • +
    +

    SD card testing

    +
      +
    • There are many fake SD card around. eBay and Amazon Marketplace are notorious for selling fakes, but sometimes even reputable retailers get fooled.
    • +
    • Most commonly low capacity cards will be reprogrammed to appear as bigger, but any files written beyond the true capacity will be lost or corrupted.
    • +
    • We recommend to always test the capacity of each new SD cards using f3.
    • +
    +

    Writing images to the SD card

    +
      +
    • If you wrote an image to the card it does not mean that it was written successfully without any errors
    • +
    • so always verify images after write using some tools like balenaEtcher which is currently the only popular and cross-platform tool that does mandatory verify on write (more lightweight alternatives may be added to this page in the future)
    • +
    • “Check for bad blocks” function available in some tools is mostly useless when dealing with SD cards
    • +
    • Note that balenaEtcher verifies only 1-2GB that are occupied by the initial unresized image, it does not verify the whole SD card
    • +
    +

    Network

    +

    MAC Address Conflicts

    +

    If you experience strange network problems, especially if you are running several of these SOC-boards with the same operating system, then the problems may be sourced by not having a real hardware MAC address. The operating systems try to generate a hardware MAC address from the CPUid, but what if that SOC has no CPUid either?

    +

    Then you have to do it manually. Depending on system and network installation, there are several possibilities:

    +
      +
    • the preferred way: change /boot/armbianEnv.txt and add a line:
      Text Only
      1
        ethaddr=XX:XX:XX:XX:XX:XX
      +
      +
    • +
    +

    but that file is interpreted by u-boot, which happens early in boot process, but not every u-boot is able to read that file.

    +
      +
    • next possibility to set mac-address is changing network configuration. On systems with ifupdown you can do that by changing /etc/network/interfaces. Add these lines:
      Text Only
      1
      +2
      +3
        auto eth0
      +  iface eth0 inet dhcp
      +      hwaddress ether XX:XX:XX:XX:XX:XX
      +
      +
    • +
    +
      +
    • if the above does not work, then your network is probably controlled by Network-manager . In directory /etc/Networkmanager/system-connections is a file Wired connection 1.nmconnection. Change entry cloned-mac-address of group [ethernet] :
      Text Only
      1
      +2
      +3
      +4
      +5
      +6
        [connection]
      +  id=Wired connection 1
      +  type=ethernet
      +
      +  [ethernet]
      +  cloned-mac-address=XX:XX:XX:XX:XX:XX
      +
      +
    • +
    +

    Video

    +

    No Screen on 4k Resolution

    +

    Some combination of boards/kernel versions does not support 4k resolution. This may cause black screen on connecting the board to 4k resolution devices. A workaround to solve this without changing the kernel is forcing the video mode to 1080p. Add this directive to the /boot/armbianEnv.txt and reboot your system:

    +
    Text Only
    1
    extraargs=video=HDMI-A-1:1920x1080@60
    +
    +
      +
    • Despite of this config, some apps may try to use 4k resolution, example: Retroarch. In this case you have to change app configuration to use the 1080p resolution.
    • +
    +
      +
    • To edit files without video you could connect to the board using ssh. Other option is mount the sd card in another device.
    • +
    +

    Configuration

    +
      +
    • Some boards require the setup of the correct device tree file or they will not boot. Check the board specific documentation for details.
    • +
    +

    How to report bugs properly

    + + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Board-Support-Rules/index.html b/611/User-Guide_Board-Support-Rules/index.html new file mode 100644 index 000000000..9c803bb4a --- /dev/null +++ b/611/User-Guide_Board-Support-Rules/index.html @@ -0,0 +1,2066 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Board Support Rules - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Board support Rules

    +

    Overview

    +

    Support definitions, criteria and relationships for:

    + +

    Platinum Support

    +

    Platinum support is reserved for business relationships with the Armbian project and is out of the scope of this document.

    +

    Contact us

    +

    Please contact Armbian management for more information.

    +

    Standard Support

    +

    Benefits

    +
      +
    • Armbian will publish and distribute “stable” images through its mirror network (behind automated closest mirror selection)
    • +
    • Armbian will publish and distribute “rolling” images (on GitHub and individual download page)
    • +
    • best-effort support to SBC maintainer to assure compatibility within the Armbian Build Framework
    • +
    • best-effort team’s unique expertise to assist maintainer with general challenges
    • +
    • best-effort automated testing for basic hardware functionality
    • +
    • best-effort compensation will be provided to maintainer from the “Armbian Community Fund” [1] [2] [3]
    • +
    +

    Requirements

    +

    For a SBC to be considered supported:

    +
      +
    • must be beneficial to the Armbian project
    • +
    • Armbian team must confirm and agree upon all supported boards statuses
    • +
    • a named individual as “maintainer” with GitHub ID must be preset in the BOARD_MAINTAINER within Board Configuration File
    • +
    • a named individual must commit to providing “best effort” support for their SBC on the Armbian forums
    • +
    • maintainer must participate in the Release Process
    • +
    • maintainer must sign-off that device has been tested, is stable, and ready for release during release process
    • +
    • maintainer must have physical access to the SBC they are supporting
    • +
    • maintainer can operate under pseudonym but must reveal his identity to Armbian management
    • +
    • maintainer should attend developers meetings held every Wednesday 7:00 PM CET
    • +
    • when whole support burden is carried by maintainer and Armbian team, it will be labelled as “Pro bono”
    • +
    +
    +Additional Caveats +
      +
    • if the burden placed on the maintainer and Armbian team is too high, crowdfunding campaign success will decide support
    • +
    • supported is not applied to a “board family” or group of related SBCs. It is per board
    • +
    • a maintainer can support multiple devices but must satisfy all requirements above per SBC
    • +
    • any individual can be a maintainer for a standard support SBC
    • +
    • missed major release will result in immediate forfeit of “Armbian Standard support” status and demotion to “Community maintained” status unless Armbian team grants exemption
    • +
    +
    +

    Community maintained

    +

    Community maintained devices are not under active supervision or development. Support status is unknown to Armbian team. It represents combined former CSC (community supported configuration) and EOS (end of support). Can be removed from Armbian code base at any time. Left as a courtesy in case a community member wants to attempt to resurrect maintenance.

    +

    Community maintained SBCs are exclusively supported by the community.

    +

    Benefits

    +
      +
    • Armbian will publish and distribute images through its mirror network
    • +
    • Armbian will publish and distribute daily rolling images
    • +
    • periodic packages are built and published into Armbian’s apt repository
    • +
    • images are untested and Armbian team won’t respond on troubles or apply any fixes.
    • +
    +

    Requirements

    +
      +
    • patch or component does not break Armbian Build Framework
    • +
    • patch or component does not break build of supported boards or other CSCs
    • +
    • pull requests needs community review. Armbian team will not review any code related to community supported SBC
    • +
    • generally considered to “work most of the time”
    • +
    • generally considered to receive periodic maintenance from community and upstream
    • +
    +

    Staging

    +

    Work in progress (WIP) status is for when a maintainer has committed to a SBC, but is not ready to ship stable images.

    +

    Benefits

    +

    All benefits of Community Supported SBCs apply to Staging as well.

    +
      +
    • periodic / nightly CLI images are published by Armbian
    • +
    • best-effort support to SBC maintainer to assure compatibility within the Armbian Build Framework
    • +
    • best-effort team’s unique expertise to assist maintainer with general challenges
    • +
    • eligible for promotion to Standard Support
    • +
    +

    Requirements

    +
      +
    • must satisfy standard support criteria
    • +
    • must show active development
    • +
    • must compile successfully most of the time
    • +
    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_FAQ/index.html b/611/User-Guide_FAQ/index.html new file mode 100644 index 000000000..30a1beef3 --- /dev/null +++ b/611/User-Guide_FAQ/index.html @@ -0,0 +1,2162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FAQ - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Frequently asked questions

    +

    This information is mainly for new/inexperienced users but could be useful for others too.

    +

    Is Armbian an operating system?

    +

    Not per se. Armbian is a build framework that allows users to create ready-to-use images with working kernels in variable userspace configurations for various single board computers (SBCs).

    +

    We do provide various prebuilt images for some boards, but mostly for users convenience.

    +

    Why I cannot simply shove a random image into my board to work like on my PC?

    +

    x86 architecture always has a traditional BIOS or UEFI. This provides a standard framework for operating systems to interact with the hardware. Most SBCs do not. ARM is improving the situation with ARM Server Ready and ARM System Ready certificates, but most SBC vendors are not yet incentivized to meet these standards.

    +

    Without such standards, many vendors quickly fork low-level bootloaders such as u-boot and make the bare minimum modifications needed.

    +

    Great reference here

    +

    Why is Armbian constantly asking for money? Free software should be free.

    +

    Making free licence software also requires best people, expensive infrastructure, tooling. It has as much or more costs as proprietary while generating no income from the licence.

    +

    tl;dr: We are asking for help that developers and project maintainers do not lose their generosity and humanity which are the driving force that generates a value. For all of us! A great deal of our work represent a big pressure on our very limited private resources. We ask you to share that burden with us.

    +

    Development time

    +

    We are covering a large swath of diverse, custom designed ARM hardware in ways, extents, and under conditions nobody else does. Keeping this service up, keeping these low end hardware functional is laborious. When releases are approaching and a lot of testing and fixing is going on, this gets up, stress intensifies. This means we have to invest let’s say at least 3.000 - 4.000 EUR of our time on top of fixed costs into this service every day just to keep it up. Without developing any serious features users wish to have. Fulfilling many of these wishes would easily cost tens of thousands in development time, which we don’t have and which we can’t get back due to it being free software. Nobody needs to buy licence for using it, and yet only a few people decide to respect the time and attention they are receiving from developers on forums.

    +

    Infrastructure and operations

    +

    We have to maintain our infrastructure where biggest costs are - once again - people’s time, followed by electricity, then hardware itself. Often we get free hardware and very rare break even with electricity costs and with people that would maintain this for us. A new sponsored board usually brings us more costs then benefits – since benefit is anyway public.

    +

    Support time

    +

    The software is given, released free. However support, development, and documentation costs time, effort, hardware and technical ability, which incurs costs.

    +

    Each question that is directed towards our team is generating opportunity costs and taking away from development time. Some we are happy to cover, but not all. Especially when it goes for repetitive questions and demands.

    +

    Questions associated with missing features represent another hit and miss for us. Complicated and critical upstream functions are missing (like video acceleration within a web browser, supporting a board that had very poor initial support and no community backing, etc.). This functionality is unique to hardware and implementing is extremely labor intensive and requires unique expertise. Our team is 10-15 volunteers that maintain this project during their own time. We cannot cover the job of Google Chromium team, Collabora, ARM, Rockchip and other vendors which have not provided sufficient support for their products.

    +

    All our work is done in public and we provide all sources which we are changing in the process. All our work is patent free and released under a free licence so anyone can re-use it further. The scale of SBCs Armbian supports is hard to beat, and consequently our work is repackaged and reused by other projects and vendors. Unfortunately the burden of support is often directed to us, while they focus on revenue.

    +

    Why does hardware feature XY work in old kernel but not in more recent one?

    +

    Vendors develop hardware specific support on fixed (usually old LTS) kernel and U-Boot fork and only do minimal adjustments to make board features work. Besides the fact that those adjustments are almost never pushed back to mainline they usually do not update their sources (if available at all) and pre-made kernels/boot loaders as well.

    +

    Armbian moves things forward and follows mainline kernel as much as possible, to provide both its features as well as security updates. The downside is that some features do not work since nobody ported specific drivers to recent mainline, and they can also break. Armbian can only afford to do brief testing of images and check if basic functions (boot-up, network, USB, etc.) work due to lack of both human and financial resources.

    +

    What does WIP/EOS/CSC mean?

    +
      +
    • WIP: Work In Progress: Basic functions can be tested but not ready for production yet.
    • +
    • CSC: Community Supported Configuration: Community contributed support. No official support from Armbian development team.
    • +
    • EOS: End of life: Support ended.
    • +
    +

    I have no technical knowledge. How can I help?

    +

    We need many different profiles of people to run this project and just about any help is appreciated, not just help on development. Since otherwise developers have to fix web pages, developers have to run projects, developers have to seek for money, developers have to maintain servers, developers have to maintain forum, developers have to moderate forums, developers have to maintain infrastructure, developers have to maintain relations with partners, developers have to waste time on repeated support question, developers have to deal with “customers”, …

    +

    Why are old-stable distributions like Ubuntu Focal or Debian Buster not supported?

    +

    The Armbian project has very limited human and financial resources so it can focus on a few up-to-date operating system releases only.
    +Currently supported userspaces from Debian and Ubuntu (latest only).

    +

    I have a TV Box or tablet from <insert random vendor>. Can I use Armbian on it?

    +

    No.

    +

    However some community members are commited to tinkering with these devices. They discuss their findings in a dedicated space in our forums. Take note that there is no support from the Armbian development team whatsoever.
    +General advice: Do not buy (cheap) tv boxes!

    +

    Why does Armbian not support tables or TV boxes in general? The market is huge!

    +

    There are some manufacturers who produce better quality than the others. In general they provide more or less accurate schematics and they have some engineers that are available for general public and you can ask them things here and there. Most of them try to keep up with the highest standards of hardware development. With proper documentation and minimal support, costs of software development are significantly lower. This is especially important, because we waste our precious private time to secure proper hardware functioning through the time.

    +

    However, in vast majority of cases, TV boxes are lacking any documentation. There are frequent changes of components without notice whatsoever, boot mechanisms are closed source and almost all Armbian builds that exist in the wild are unofficial community hacks. Market is huge but since public does not have interest in covering of support - which in this case is even bigger - involvement in providing support is simply insane and stupid. It only eats our personal time and finances.

    +

    There is a new board on the market. Will Armbian officially support it?

    +

    Maybe. It depends on things like available documentation from both the vendor as well as SoC manufacturer, production samples to play with, available BSP and last but certainly not least human resources. To say a Maintainer within the Armbian development team to agree taking care. Also if vendors decide to support Armbian there is certainly a higher chance to get it fully supported.

    +

    How can I compile my own kernel?

    +

    Normally on Debian or Ubuntu you would do something like sudo apt-get build-dep linux linux-image-$(uname -r).
    +However Armbian’s way of building kernel images is slightly different than the standard distribution method. The best way is to follow the procedures in the Developer Guide.

    +

    Why I cannot choose a specific kernel version (5.11.5 for example)?

    +

    Each kernel Armbian offers has a custom patchset on top which would be impossible to maintain compatibility to each and every kernel version out there. Therefore the choice is usually limited to up to three branches: legacy, current and edge. Depending on board/family the versions behind these branches may differ. You can lookup them in the source code.

    +

    Can I upgrade my userspace flavor, like Bullseye to Bookworm or Jammy to Noble?

    +

    Note: Upgrading the Armbian core packages like kernel, firmware and boot loader and the chosen userspace are independent processes. Former is simply done with apt update && apt upgrade.

    +

    Armbian does not offer a standardized way nor do we encourage users to upgrade their userspace, like Focal to Jammy, Jammy to Noble, Bullseye to Bookworm, Bookworm to Trixie. We would love to do that but the reason why we cannot is simply the lack of ressources in time and devices to test such upgrades in various random scenarios.

    +

    You can try to upgrade your userspace by following official ways from Debian/Ubuntu but make sure to freeze your firmware packages via armbian-config beforehand. Also please do not blame/complain (at) Armbian if something goes wrong or have other issues with an upgraded system.

    +

    Where do I ship a board so that Armbian will add support?

    +

    Unless you have an existing arrangement with the Armbian, you will need to contact Armbian for a paid engagement.
    +You may also add support by yourself if criteria is satisfied. See Board Support Rules for further information.

    +

    What WiFi adapters will most likely work out of the box?

    +

    Check here.

    +

    I cannot find armbian-config on my device.

    +

    If you are using a minimal variant this tool is not pre-installed. However you can simply install it via sudo apt update && sudo apt install armbian-config which will also handle all necessary dependencies.
    +If you are not using an minimal image and the tool is still missing make sure your image is genuine.

    +

    Why keeps one of the leds flashing twice over and over like a heartbeat? Is there something wrong?

    +

    Absolutely not. Quite the contrary. This behaviour is called heartbeat trigger and is controlled by the kernel. When the load increases the flashing speed will increase as well. If the flashing stops the kernel either froze or were unloaded by either reboot or shutdown.
    +Unhappy? Keep reading below :-)

    +

    Can this behaviour adjusted/disabled?

    +

    Maybe. Some boards have certain functions hard-wired to the onboard leds. Others allow to control the led functions from userspace.
    +Try to find trigger files for the leds in /sys.
    +Example for an Orange Pi One: +

    Text Only
    1
    +2
    +3
    root@orangepione:~# find /sys/devices -name trigger | grep led
    +/sys/devices/platform/leds/leds/orangepi:red:status/trigger
    +/sys/devices/platform/leds/leds/orangepi:green:pwr/trigger
    +
    +Use cat on the trigger file to both check its current behaviour, which is highlighted with [brackets], and which functions are supported. Then use echo to adjust the behaviour. +Example for disabling a led: +
    Text Only
    1
    +2
    +3
    root@orangepione:~# cat /sys/devices/platform/leds/leds/orangepi:red:status/trigger
    +none rc-feedback kbd-scrolllock kbd-numlock kbd-capslock kbd-kanalock kbd-shiftlock kbd-altgrlock kbd-ctrllock kbd-altlock kbd-shiftllock kbd-shiftrlock kbd-ctrlllock kbd-ctrlrlock usbport disk-activity disk-read disk-write ide-disk mtd nand-disk [heartbeat] cpu cpu0 cpu1 cpu2 cpu3 activity default-on panic mmc0 rfkill-any rfkill-none 0.1:01:link 0.1:01:100Mbps 0.1:01:10Mbps
    +root@orangepione:~# echo none > /sys/devices/platform/leds/leds/orangepi:red:status/trigger
    +

    +

    Why is there no image for [board] with [Bookworm/Jammy/Noble/Trixie] and [Minimal/CLI/Gnome/KDE/Xfce] with [vendor/legacy/current/edge] kernel?

    +

    It would be VERY ressource intensive and just insane to pre-create and provide images for all possible combination of kernels, userspaces and desktops/CLI for all available boards and last but not least provide support for them. We simply cannot afford doing this since our ressources in both human and financial are limited. Therefore we provide a small selection for each board only.
    +However with the Armbian build framework it is very easy and convenient to create an image of your desire by yourself.
    +If there is enough public interest for a certain combination we may occasionally adjust our build targets.

    +

    When using the framework it does not build anything but downloads artifacts. How can I force rebuilding from sources?

    +

    tl;dr: ARTIFACT_IGNORE_CACHE=yes

    +

    Forcing a rebuild is usually not necessary, because:

    +
    +

    Armbian build […] operates on smaller units called “artifacts”: the kernel, u-boot, firmware, rootfs, and then finally the full image. Each of those has its version calculated beforehand based on its would-be +contents, and looked up in both a local and remote cache (OCI registry), allowing users to re-use artifacts across builds and to use the best hardware available for each. […]

    +
    +

    However sometimes local changes are not detected properly. Therefore this flag can be useful.

    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Fine-Tuning/index.html b/611/User-Guide_Fine-Tuning/index.html new file mode 100644 index 000000000..89001ff45 --- /dev/null +++ b/611/User-Guide_Fine-Tuning/index.html @@ -0,0 +1,2228 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fine Tuning - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    How to customize keyboard, time zone?

    +
      +
    • Attention: The preferred method to change most of this stuff is by using the interactive armbian-config tool which is shipped with all Armbian images.
    • +
    +

    Keyboard:

    +
    Text Only
    1
    dpkg-reconfigure keyboard-configuration
    +
    +

    In some cases, e.g. when your keyboard standard is not available in previous command, you may also need to set your keymap config:

    +
    Text Only
    1
    +2
    +3
    +4
    +5
    # Check your actual keymap config
    +localectl status | grep -i keymap
    +
    +# Set the desired keymap config. Example below to 'br-abnt2'
    +localectl set-keymap br-abnt2
    +
    +

    System language:

    +
    Text Only
    1
    +2
    +3
    +4
    # Debian --> https://wiki.debian.org/ChangeLanguage
    +dpkg-reconfigure locales
    +# Ubuntu --> https://help.ubuntu.com/community/Locale
    +update-locale LANG=[options] && dpkg-reconfigure locales
    +
    +

    Console font, codepage:

    +
    Text Only
    1
    dpkg-reconfigure console-setup
    +
    +

    Time zone:

    +
    Text Only
    1
    dpkg-reconfigure tzdata
    +
    +

    Sound output:

    +
    Text Only
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    # Check the available sound output options:
    +pacmd list-sinks | less
    +# The default will be marked with "*"
    +# Press "q" to close
    +
    +
    +# Define the new default sound output
    +pacmd set-default-sink <NAME-OF-DESIRED-OPTION>
    +
    +

    The name of HDMI sound output may change accordingly to the device. If you don’t wanna deal with different names you can:

    +
    Text Only
    1
    pacmd set-default-sink $(pactl list short sinks | grep -i 'hdmi' | awk '{print $2}')
    +
    +

    The command to define the default sound output is not persistent, to make it persistent add it to the file ~/.bashrc

    +

    Screen resolution on other boards:

    +
    Text Only
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    nano /boot/boot.cmd
    +
    +# example:
    +# change example from
    +# disp.screen0_output_mode=1920x1080p60
    +# to
    +# disp.screen0_output_mode=1280x720p60
    +
    +mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr
    +
    +

    Screen resolution within Xorg

    + +

    Find matching HDMI output:

    +
    Text Only
    1
    xrandr --listmonitors
    +
    +

    Calculate VESA CVT mode lines (example for 1440x900)

    +
    Text Only
    1
    cvt 1440 900
    +
    +

    Sample output:

    +
    Text Only
    1
    +2
    1440x900 59.89 Hz (CVT 1.30MA) hsync: 55.93 kHz; pclk: 106.50 MHz
    +Modeline "1440x900_60.00"  106.50  1440 1528 1672 1904  900 903 909 934 -hsync +vsync )
    +
    +

    Create new mode (example):

    +
    Text Only
    1
    xrandr --newmode "1440x900_60.00" 106.50 1440 1528 1672 1904 900 903 909 934 -hsync +vsync
    +
    +

    Add resolution (example):

    +
    Text Only
    1
    xrandr --addmode HDMI-1 1440x900_60.00
    +
    +

    Set current resolution (example):

    +
    Text Only
    1
    xrandr --output HDMI-1 --mode 1440x900_60.00
    +
    +

    If it works as expected add it to Xorg by editing /etc/X11/xorg.conf.d/40-monitor.conf and add (example):

    +
    Text Only
    1
    +2
    +3
    +4
    +5
    Section "Monitor"
    +Identifier "HDMI-1"
    +Modeline "1440x900_60.00" 106.50 1440 1528 1672 1904 900 903 909 934 -hsync +vsync
    +Option "PreferredMode" "1440x900"
    +EndSection
    +
    +

    Restart Xorg or reboot

    +

    How to alter CPU frequency?

    +

    Some boards allow to adjust CPU speed

    +
    Text Only
    1
    nano /etc/default/cpufrequtils
    +
    +

    Alter min_speed or max_speed variable.

    +
    Text Only
    1
    systemctl restart cpufrequtils
    +
    +

    Swap for experts

    +

    By default Armbian implements ZRAM (writing nothing to ‘disk’ but compressing memory pages in RAM) but in case you often run into out of memory errors and your device has some capable storage (e.g. a securely attached NVMe or SATA SSD) you might want to use ZSWAP instead.

    +

    Check whether your kernel has zswap enabled (dmesg | grep zswap should output something) and if so create a swapfile or swap partition the traditional way, edit/uncomment /etc/default/armbian-zram-config so that it reads SWAP=false, reboot and you’re done.

    +

    Zswap performs a lot better than the combination of ZRAM and ‘swap on disk’ in parallel.

    +

    How to downgrade a package via apt?

    +

    This is useful when you need to fall back to previous kernel version.

    +
    Text Only
    1
    apt install linux-image-sun8i=5.13
    +
    +

    This example is for H3 legacy kernel. Check this page for others.

    +

    How to toggle boot output?

    +

    Edit and change boot parameters in /boot/boot.cmd (not recommended) or variables in /boot/armbianEnv.txt:

    +
    Text Only
    1
    +2
    - console=both
    ++ console=serial
    +
    +

    To disable console entirely (not recommended) set console to none.

    +

    Recompile boot.cmd to boot.scr if it was changed:

    +
    Text Only
    1
    mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr
    +
    +

    Reboot.

    +

    Serial console on imx6 boards are ttymxc0 (Hummingboard, Cubox-i) or ttymxc1 (Udoo).

    +

    How to toggle verbose boot?

    +

    Using Armbian 5.05 to 5.20 you would need to touch/rm /boot/.force-verbose to increase boot verbosity. With more recent Armbian builds you would have to alter the verbosity= line in /boot/armbianEnv.txt (defaults to 1 which means less verbose, maximum value is 7).

    +

    How to provide boot logs for inspection?

    +

    When your SBC behaves strange first step is to check power supply and integrity of boot media (armbianmonitor -c "$HOME"). Then look into your kernel logs. We made a tool that grabs info and pastes it to an online pasteboard service. Please increase boot verbosity as shown above (verbosity=7), reboot and then run

    +
    Text Only
    1
    sudo armbianmonitor -u
    +
    +

    Copy and past URL of your log to the forum, mail, …

    +

    How to change network configuration?

    +

    To get Wi-Fi working simply use nmtui, a simple console based UI for network-manager (an example how to set up an AP with network-manager can be found here). To deal with different Ethernet/Wi-Fi combinations there are six predefined configurations available, you can find them in those files:

    +
    Text Only
    1
    +2
    +3
    +4
    +5
    +6
    /etc/network/interfaces.bonding
    +/etc/network/interfaces.default
    +/etc/network/interfaces.hostapd
    +/etc/network/interfaces.network-manager
    +/etc/network/interfaces.r1
    +/etc/network/interfaces.r1switch
    +
    +

    By default /etc/network/interfaces is a copy of /etc/network/interfaces.default

    +
      +
    1. BONDING: your network adapters are bonded in fail safe / “notebook” way.
    2. +
    3. DEFAULT: your network adapters are connected classical way.
    4. +
    5. HOSTAPD: your network adapters are bridged together and bridge is connected to the network. This allows you to have your AP connected directly to your router.
    6. +
    7. All interfaces are handled by network-manager (nmtui/nmcli or using the GUI)
    8. +
    9. Router configuration for Lamobo R1 / Banana R1.
    10. +
    11. Switch configuration for Lamobo R1 / Banana R1.
    12. +
    +

    You can switch configuration with copying.

    +
    Text Only
    1
    +2
    cd /etc/network
    +cp interfaces.x interfaces
    +
    +

    (x = default,hostapd,bonding,r1)

    +

    Then check / alter your interfaces:

    +
    Text Only
    1
    nano /etc/network/interfaces
    +
    +

    Choosing an apt mirror

    +

    Armbian has its own apt repository and mirrors for armbian-specific packages. The default of http://apt.armbian.com is a round-robin to all mirrors. If you are having trouble updating or slow speeds you may want to choose a specific mirror.

    +

    Do the following:

    +

    Assure jq is installed

    +

    apt install -y jq

    +

    Get a list of available mirrors from our https://apt.armbian.com/mirrors endpoint.

    +
    Bash
    curl -s http://apt.armbian.com/mirrors|jq
    +
    +

    You will see a result set similar to this, listing mirrors by region: +

    JSON
     1
    + 2
    + 3
    + 4
    + 5
    + 6
    + 7
    + 8
    + 9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    {
    +  "AS": [
    +    "https://mirrors.tuna.tsinghua.edu.cn/armbian/",
    +    "https://minio.k-space.ee/armbian/apt/"
    +  ],
    +  "NA": [
    +    "https://armbian.tnahosting.net/apt/",
    +    "https://us.mirrors.fossho.st/armbian/apt/"
    +  ],
    +  "EU": [
    +    "https://minio.k-space.ee/armbian/apt/",
    +    "https://armbian.systemonachip.net/apt/",
    +    "https://mirrors.netix.net/armbian/apt/",
    +    "https://mirrors.dotsrc.org/armbian-apt/",
    +    "https://armbian.hosthatch.com/apt/"
    +  ],
    +  "default": [
    +    "https://armbian.tnahosting.net/apt/",
    +    "https://us.mirrors.fossho.st/armbian/apt/",
    +    "https://minio.k-space.ee/armbian/apt/",
    +    "https://armbian.systemonachip.net/apt/",
    +    "https://mirrors.netix.net/armbian/apt/",
    +    "https://mirrors.dotsrc.org/armbian-apt/",
    +    "https://armbian.hosthatch.com/apt/"
    +  ]
    +}
    +

    +

    Edit /etc/apt/sources.list.d/armbian.list and replace the url http://apt.armbian.com with your preferred mirror.

    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Getting-Started/index.html b/611/User-Guide_Getting-Started/index.html new file mode 100644 index 000000000..ac02aaf63 --- /dev/null +++ b/611/User-Guide_Getting-Started/index.html @@ -0,0 +1,2315 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Getting Started - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Armbian Quick Start Guide

    + + +
    +

    New users

    +

    Please, make sure you have:

    +
      +
    • a proper power supply according to the board manufacturer requirements
    • +
    • a reliable SD card (see below “How to prepare a SD card?”)
    • +
    +
    +

    What to download

    +

    The download for each image consists of three separate files:

    +
      +
    • .xz compressed image file
    • +
    • .sha file for download verification (optional)
    • +
    • .asc file for image authentication (optional)
    • +
    +
    +

    How to check download authenticity?

    +

    All our images are digitally signed and therefore it is possible to check their authenticity. You need to issue these commands (Linux/macOS, you might need to install dependencies first, eg. sudo apt-get install gnupg on Debian/Ubuntu or brew install gnupg on macOS. on windows install the current simple gnupg Gnupg:

    +

    Bash
     1
    + 2
    + 3
    + 4
    + 5
    + 6
    + 7
    + 8
    + 9
    +10
    +11
    +12
    # download public key from the database
    +gpg --keyserver hkp://keyserver.ubuntu.com --recv-key DF00FAF1C577104B50BF1D0093D6889F9F0E78D5
    +# perform verification 
    +gpg --verify Armbian_5.18_Armada_Debian_jessie_3.10.94.img.xz.asc
    +
    +# proper response
    +gpg: Signature made sob 09 jan 2016 15:01:03 CET using RSA key ID 9F0E78D5
    +gpg: Good signature from "Igor Pecovnik (Ljubljana, Slovenia) <igor.++++++++++++@gmail.com>"
    +
    +# wrong reponse. Not genuine Armbian image!
    +gpg: Signature made Sun 03 Jan 2016 11:46:25 AM CET using RSA key ID 9F0E78D5
    +gpg: BAD signature from "Igor Pecovnik (Ljubljana, Slovenia) <igor.++++++++++++@gmail.com>"
    +
    +It is safe to ignore the message WARNING: This key is not certified with a trusted signature!.

    +
    +
    +

    How to check download integrity?

    +

    Since it might happen that your download got somehow corrupted we integrate a checksum/hash for the image. You can compare the image’s SHA-256 hash with the one contained in the sha256sum.sha file.

    +

    On Windows, you can download and use the QuickHash GUI and follow the instructions in the gui.

    +

    while on Linux/macOS, in the directory in which you have downloaded the files ,you would do this

    +
    Bash
    1
    +2
    +3
    +4
    shasum -a 256 -c Armbian_*.img.sha
    +
    +#good response
    +Armbian_5.35_Clearfogpro_Debian_stretch_next_4.13.16.img: OK
    +
    +
    +

    For each board we usually provide various image types:

    +
      +
    • Minimal - lightweight CLI with bare minimum of packages
    • +
    • Server - server variant with preinstalled standard utilities
    • +
    • Desktop full featured desktop image
    • +
    +

    For some boards we provide only minimal images due to their hardware limitations.

    +

    Debian or Ubuntu?

    +

    If you have no special preferences that require specific versions, we recommend Ubuntu based Armbian.

    +

    Vendor, current?

    +

    In some cases we provide images with different firmware. They differ in level of hardware support. Focus into:

    +
      +
    • vendor contains vendor provided kernel which usually has best hardware support while version can be outdated, containin less general fixes
    • +
    • current is following latest mainline LTS kernel and is in most cases best choice
    • +
    +

    And use those if they are the only one / for testings:

    +
      +
    • edge is as the name implies cutting-edge fresh / development / latest stable. It is only automatically tested and can break at any time. Recommended for experienced users.
    • +
    • legacy is old stable current kernel. Use if either current is not available or something does not work well with it.
    • +
    +

    The level of kernel support however always depends on the board family. If in your specific case something does not work well, you are always free to try an image with an other kernel included or change kernel within armbian-config.

    +

    Rolling releases?

    +

    Rolling releases are suitable for Linux enthusiasts who want cutting edge packages and have the skills to fix damage that a bad update might cause. If you want stability in a production environment or low headaches as a novice user, skip rolling releases. They are only at, build and ship, Debian testing / Arch / Manjaro / Suse Tumbleweed / Kali / Gentoo support quality level!

    +
    graph LR
    +  A[Hardware] --> B{Armbian kernel};
    +  B -->|legacy| C["rolling release"];
    +  B -->|vendor| C["rolling release"];
    +  B -->|current| C["rolling release"];
    +  B -->|edge| C["rolling release"];
    +  B -->|legacy| X["point release"];
    +  B -->|vendor| X["point release"];
    +  B -->|current| X["point release"];
    +  B -->|edge| X["point release"];
    +
    +
    +  C ---->|minimal| E[Debian or Ubuntu];
    +  C ---->|server| F[Debian or Ubuntu];
    +  C ---->|desktop| G[Debian or Ubuntu];
    +
    +  X ---->|minimal| E[Debian or Ubuntu];
    +  X ---->|server| F[Debian or Ubuntu];
    +  X ---->|desktop| G[Debian or Ubuntu];
    +
    +

    Danger

    +

    Do not use rollling or edge images in a productive environment. Their purpose is testing and providing constructive feedback to developers.

    +
    +

    Preparing SD card

    +

    Important note: Make sure you use a good, reliable and fast SD card. If you encounter boot or stability troubles in over 95 percent of the time it is either insufficient power supply or related to SD card (bad card, bad card reader, something went wrong when burning the image, card too slow to boot – ‘Class 10’ highly recommended!). Armbian can simply not run on unreliable hardware so checking your SD card with either F3 or H2testw is mandatory if you run in problems. Since counterfeit SD cards are still an issue checking with F3/H2testw directly after purchase is highly recommended.

    +

    Write the .xz compressed image to your microSD card. Using USBImager on all platforms is recommended since, unlike other tools, it can validate written data saving you from corrupted SD card contents. Due to known issues using BalenaEtcher is not recommended at this time.

    +
    +

    Also important

    +

    Most SD cards are only optimised for sequential reads/writes as it is common with digital cameras. This is what the speed class is about. The SD Association defined Application Performance Class as a standard for random IO performance.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Application Performance ClassPictographMiniumum Random ReadMinimum Random WriteMinimum Sustained (Seq. Write)
    Class 1 (A1)a1-logo1500 4k IOPS500 4k IOPS10MBytes/sec
    Class 2 (A2)a2-logo4000 4k IOPS2000 4k IOPS10MBytes/sec
    +

    We recommend at least A1 rated SD-Cards (A2 rated cards need yet lacking driver support and therefore show lower overall and especially random IO performance). For example:

    +

    a1-16gb-card a1-32gb-card a2-64gb-card

    +

    In case you chose an SD card that was already in use before please consider resetting it back to ‘factory default’ performance with SD Formatter before burning Armbian to it (explanation in the forum). Detailed information regarding ‘factory default’ SD card performance.

    +

    How to boot

    +

    Insert SD card into a slot and power the board. (First) boot (with DHCP) takes up to two minutes with a class 10 SD card and cheapest board.

    +

    How to login

    +

    First boot will log you automatically on HDMI or serial console while for SSH login you need to login as root and use password 1234. You will be prompted to change this password. You will then be asked to create a normal user account that is sudo enabled (beware of default QWERTY keyboard settings at this stage). Please use this tool, to find your board IP address.

    +
    +Automated config +

    These settings can be pre-loaded, see Autoconfig

    +
    +

    In case you have no wired network connection and there is a wireless adaptor detected, it will prompt you to connect.

    +
    Text Only
     1
    + 2
    + 3
    + 4
    + 5
    + 6
    + 7
    + 8
    + 9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    Welcome to Armbian!
    +
    +Documentation: https://docs.armbian.com/ | Community support: https://forum.armbian.com/
    +
    +IP address:  Network connection timeout!
    +
    +Create root password: ********
    +Repeat root password: ********
    +
    +Shell: BASH
    +
    +Creating a new user account. Press <Ctrl-C> to abort
    +
    +Please provide a username (eg. your first name): jane
    +Create user (Jane) password: ********
    +Repeat user (Jane) password: ********
    +
    +Please provide your real name: Jane
    +
    +Dear Jane, your account jane has been created and is sudo enabled.
    +Please use this account for your daily work from now on.
    +
    +Internet connection was not detected.
    +
    +Connect via wireless? [Y/n] y
    +
    +Multiple wireless adaptors detected. Choose primary:
    +
    +1        wlx00e032cxxx94
    +2        wlx60fb00yyyc4a
    +
    +Enter a number of wireles adaptor: 1
    +
    +Detected wireless networks:
    +
    +1        NETWORK
    +2        MY-WIFI
    +3        Caatsanddogs
    +
    +Enter a number of SSID: 3
    +
    +Enter a password for MY-WIFI: password
    +
    +Probing internet connection (9)
    +
    +Detected timezone: Europe/Ljubljana
    +
    +Set user language based on your location? [Y/n] y
    +
    +Generating locales: sl_SI.UTF-8
    +root@bananapim2pro:~#
    +
    +

    How to install

    +

    Installer

    +
    +

    Required condition for eMMC/SATA/USB/NVME:

    +
      +
    • onboard eMMC storage
    • +
    • attached SATA, NVME or USB storage
    • +
    +
    +

    Start the install script and follow the lead:

    +
    Text Only
    1
    armbian-install
    +
    +
    +

    Armbian installer provides those scenarios:

    +
      +
    • boot from SD, system on SATA / USB
    • +
    • boot from eMMC / NAND, system on eMMC/NAND
    • +
    • boot from eMMC / NAND, system on SATA / USB / NVME
    • +
    • Boot from SPI - system on SATA, USB or NVMe
    • +
    • Install/Update the bootloader on SD/eMMC
    • +
    • Install/Update the bootloader on special eMMC partition
    • +
    • Install/Update the bootloader on SPI Flash
    • +
    • Install system to UEFI disk
    • +
    +
    +
    +

    You can choose the following file system options:

    +
      +
    • ext2,3,4
    • +
    • btrfs
    • +
    +
    +

    How to update

    +

    Armbian OS

    +
    Text Only
    1
    +2
    apt update
    +apt upgrade
    +
    +

    Update process can take some time in case of using old & cheap SD card and/or under heavy load.

    +

    If the kernel was upgraded during this process you will be prompted to reboot at next login.

    +

    Boot loader

    +

    First you need to update all packages described in a previous step. Then run:

    +
    Bash
    sudo armbian-install
    +
    +

    Select:

    +

    Install/Update the bootloader on SD/eMMC

    +

    How to stay safe

    +

    Armbian provides firmware package freeze to give you an option to upgrade all packages but firmware. This prevents unplesant surprises on functionality regressions that comes with kernel upgrades. To enable / disable this feature, look for Enable Armbian kernel/firmware upgrades / Disable Armbian kernel upgrades within armbian-config.

    +

    How to upgrade a distribution

    +

    When a new userspace is out, we recommend to start with a fresh image. However, it is possible to upgrade, but the process is largerly in the domain of underlaying Debian or Ubuntu user space. However we provide experimental Distribution upgrades within armbian-config

    +
    +

    Danger

    +

    Userspaces distribution upgrades are neither tested nor supported. Therefore Armbian cannot provide support if something goes wrong.

    +
    +

    How to tune hardware

    +

    Hardware configuration is available within armbian-config utility.

    +

    How to report bugs

    +

    Follow bug reporting form available here and learn how to collect necessary information and where provide to put your report depending on type of issue. Reports lacking fundamental diagnostics are ignored.

    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Networking/index.html b/611/User-Guide_Networking/index.html new file mode 100644 index 000000000..130c17e8d --- /dev/null +++ b/611/User-Guide_Networking/index.html @@ -0,0 +1,2174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Networking - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Networking

    +

    Armbian uses Netplan.io to describe networking configurations. Netplan is a utility to easily configure Linux networking, using a declarative approach. +If you want to configure your network manually, it is as simple as editing and creating Netplan yaml files (see the yaml configuration reference at the Netplan docs).

    +

    Netplan is used to configure networks on all Armbian images since Release 24.05, no matter if minimal, CLI or desktop, Debian or Ubuntu. However, the networking backends are different based on if you choose a minimal image or not.

    +

    Minimal images

    +
    +

    Netplan renderer: networkd

    +
    +

    Minimal images are using the systemd-networkd backend, which has a smaller footprint compared to Network-Manager which is used in all non-minimal images. systemd-networkd is a system daemon that manages network configurations. It detects and configures network devices as they appear; it can also create virtual network devices. This service is great for simple connections, but can also be useful to set up complex network configurations.

    +

    Armbian defaults

    +

    All ethernet interfaces are configured for DHCP and will automatically receive an IP address from your router.

    +

    /etc/netplan/10-dhcp-all-interfaces.yaml:

    +
    YAML
     1
    + 2
    + 3
    + 4
    + 5
    + 6
    + 7
    + 8
    + 9
    +10
    network:
    +  version: 2
    +  renderer: networkd
    +  ethernets:
    +    all-eth-interfaces:
    +      match:
    +        name: "e*"
    +      dhcp4: yes
    +      dhcp6: yes
    +      ipv6-privacy: yes
    +
    +

    Configuration examples

    +

    Setting a fixed IP address

    +

    The following example configures a static IP 192.168.1.199 for the eth0 interface. Please adjust as necessary.

    +
    +

    How to find your device’s Ethernet interface?

    +

    Use command:

    +

    Bash
    ip addr
    +
    +It is usually something like eth0, enp4s3 or lan.

    +
    +

    /etc/netplan/20-static-ip.yaml:

    +
    YAML
     1
    + 2
    + 3
    + 4
    + 5
    + 6
    + 7
    + 8
    + 9
    +10
    +11
    +12
    +13
    +14
    network:
    +  version: 2
    +  renderer: networkd
    +  ethernets:
    +    eth0: # Change this to your ethernet interface
    +      addresses:
    +      - 192.168.1.199/24
    +      routes:
    +      - to: default
    +        via: 192.168.1.1
    +      nameservers:
    +       addresses:
    +         - 9.9.9.9
    +         - 1.1.1.1
    +
    +

    See also the Netplan docs for reference.

    +

    Connecting to WiFI network

    +
    +

    It is recommended to make a separate config file for wireless network.

    +
    +

    Create the following file:

    +

    sudo nano /etc/netplan/30-wifis-dhcp.yaml:

    +
    YAML
     1
    + 2
    + 3
    + 4
    + 5
    + 6
    + 7
    + 8
    + 9
    +10
    network:
    +  version: 2
    +  renderer: networkd
    +  wifis:
    +    wlan0:
    +      dhcp4: true
    +      dhcp6: true
    +      access-points:
    +        "Your-SSID":
    +          password: "your-password"
    +
    +

    Replace SSID with the name of the network you want to connect to and wlan0 with the wifi interface used on your system.

    +
    +

    How to find your device’s WiFi interface?

    +

    Use command:

    +

    Bash
    iw dev | awk '$1=="Interface"{print $2}'
    +
    +It is usually something like wlan0, wlo1 or wlx12334c47dec3. If you get blank response, it means your WiFi device / dongle is not supported by the kernel.

    +
    +

    See also the Netplan docs for reference.

    +

    Applying your configuration

    +

    Once you are done configuring your network, it is time to test syntax and apply it.

    +

    Fix file permissions

    +

    According to the Netplan docs, the permissions must be restricted to the root user.

    +
    Bash
    sudo chmod 600 /etc/netplan/*.yaml
    +
    +

    Test syntax

    +

    This will verify the syntax and test if your device can connect

    +
    Bash
    sudo netplan try
    +
    +

    Apply the configuration

    +
    Bash
    sudo netplan apply
    +
    +

    CLI and desktop images

    +
    +

    Netplan renderer: Network Manager

    +
    +

    Server CLI and desktop images are using the Network-Manager backend. You can use similar methods for configuring your network as with the networkd backend used on minimal images.

    +

    Setting a fixed IP address

    +

    The following example configures a static IP 192.168.1.199 for the eth0 interface. Please adjust the example to your likings.

    +
    +

    How to find your device’s Ethernet interface?

    +

    Use command:

    +

    Bash
    ip addr
    +
    +It is usually something like eth0, enp4s3 or lan.

    +
    +

    /etc/netplan/20-static-ip.yaml:

    +
    YAML
     1
    + 2
    + 3
    + 4
    + 5
    + 6
    + 7
    + 8
    + 9
    +10
    +11
    +12
    +13
    +14
    network:
    +  version: 2
    +  renderer: NetworkManager # Different than 'networkd'
    +  ethernets:
    +    eth0: # Change this to your ethernet interface
    +      addresses:
    +      - 192.168.1.199/24
    +      routes:
    +      - to: default
    +        via: 192.168.1.1
    +      nameservers:
    +       addresses:
    +         - 9.9.9.9
    +         - 1.1.1.1
    +
    +

    See also the Netplan docs for reference.

    +

    Alternatively, you can also use Network-Manager directly via the command line or GUI tools on your desktop:

    +
    Bash
    nmtui-edit eth0
    +
    +
    +Display screenshot +

    +
    +

    Replace eth0 with the name of your Ethernet Interface.

    +

    Connecting to WiFI network

    +

    For connecting to a wireless network, you can use the same method as mention above for use with networkd on minimal images. Just make sure to replace renderer: networkd with renderer: NetworkManager.

    +

    Alternatively, you can also use Network-Manager directly via the command line or GUI tools on your desktop:

    +
    Bash
    nmtui-connect SSID
    +
    +
    +Display screenshot +

    +
    +

    Replace SSID with the name of your wireless network.

    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/User-Guide_Recovery/index.html b/611/User-Guide_Recovery/index.html new file mode 100644 index 000000000..0c891a78d --- /dev/null +++ b/611/User-Guide_Recovery/index.html @@ -0,0 +1,2016 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Recovery - Armbian Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + + + +
    + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + +

    Recovery

    +

    Important: If you came here since you cannot get Armbian running on your board please keep in mind that in 95 percent of all cases it is either a faulty/fraud/counterfeit SD card or an insufficient power supply that is causing these sorts of does not work issues!

    +

    The following are presented in (more or less) increasing levels of despair. But keep heart! :) And proceed in order.

    +

    U-Boot Shell Access

    +

    If you broke the system you can try to get in this way. You have to get to u-boot command prompt, using either a serial adapter or monitor and usb keyboard.

    +
      +
    • Note: USB support in u-boot is currently not enabled on all H3 boards.
    • +
    +

    After switching power on or rebooting, when u-boot loads up, press some key on the keyboard (or send some key presses via terminal) to abort default boot sequence and get to the command prompt:

    +
    Bash Session
    1
    +2
    +3
    +4
    U-Boot SPL 2015.07-dirty (Oct 01 2015 - 15:05:21)
    +...
    +Hit any key to stop autoboot:  0
    +sunxi#
    +
    +

    Enter the following commands, replacing root device path if necessary.

    +
      +
    • Note: these are for booting with mainline kernel; check boot.cmd for your device for commands related to legacy kernel.
    • +
    +

    For serial:

    +
    Bash Session
    sunxi# setenv bootargs init=/bin/bash root=/dev/mmcblk0p1 rootwait console=ttyS0,115200
    +
    +

    For monitor:

    +
    Bash Session
    sunxi# setenv bootargs init=/bin/bash root=/dev/mmcblk0p1 rootwait console=tty1
    +
    +

    Then:

    +
    Bash Session
    1
    +2
    +3
    +4
    sunxi# ext4load mmc 0 0x49000000 /boot/dtb/${fdtfile}
    +sunxi# ext4load mmc 0 0x46000000 /boot/zImage
    +sunxi# env set fdt_high ffffffff
    +sunxi# bootz 0x46000000 - 0x49000000
    +
    +

    System should eventually boot to bash shell:

    +
    Bash Session
    root@host:/#
    +
    +

    Now you can try to fix your broken system.

    +

    Replacing /boot

    +

    When something goes terribly wrong and you are not able to boot the system (and cannot gain access via u-boot as outlined above), this is the way to proceed. You will need some Debian based Linux machine where you can mount the failed SD card. With this procedure you will reinstall the kernel and hardware settings. In most cases this should be enough to unbrick the board.

    +

    It is recommended to issue a filesystem check before mounting. Replace X and Y below with your device and partition(s), respectively (if not a flash based device, it may even be /dev/sdXY, etc).

    +
    Bash Session
    / # fsck /dev/mmcblkXpY -f
    +
    +

    Mount the SD card.

    +
    Bash Session
    1
    +2
    +3
    / # cd /mnt
    +/mnt # mkdir sdcard
    +/mnt # mount /dev/mmcblkXpY /mnt/sdcard
    +
    +

    Make another temporary directory somewhere else (in our example ~/tmp/recovery) and download the Linux root, kernel, firmware and dtb packages for your board and currently used OS.

    +
      +
    • Note: This example is only for Nanopi Neo 2 with Ubuntu Focal, current kernel (mainline) and Armbian 20.08.13 firmware. Alter package names according to your device name, SOC-family, kernel and firmware version!
    • +
    +
    Bash Session
     1
    + 2
    + 3
    + 4
    + 5
    + 6
    + 7
    + 8
    + 9
    +10
    +11
    +12
    +13
    +14
    +15
    /mnt $ cd
    +~ $ mkdir -p tmp/recovery
    +~ $ cd tmp/recovery
    +
    +(Root file system):
    +~/tmp/recovery $ wget https://apt.armbian.com/pool/main/l/linux-focal-root-current-nanopineo2/linux-focal-root-current-nanopineo2_20.08.13_arm64.deb
    +
    +(Kernel):
    +~/tmp/recovery $ wget https://apt.armbian.com/pool/main/l/linux-5.8.16-sunxi64/linux-image-current-sunxi64_20.08.13_arm64.deb
    +
    +(Firmware):
    +~/tmp/recovery $ wget https://apt.armbian.com/pool/main/a/armbian-firmware/armbian-firmware_20.08.13_all.deb
    +
    +(Device Tree Binary (DTB)):
    +~/tmp/recovery $ wget https://apt.armbian.com/pool/main/l/linux-5.8.16-sunxi64/linux-dtb-current-sunxi64_20.08.13_arm64.deb
    +
    +

    Extract all the Debian packages (.deb files) to the mounted sd card.

    +
    Bash Session
    ~/tmp/recovery # for f in *.deb; do dpkg -x $f /mnt/sdcard; done
    +
    +

    Navigate to /mnt/sdcard/boot and create symlinks:

    +
    Bash Session
    1
    +2
    +3
    +4
    ~/tmp/recovery # cd /mnt/sdcard/boot
    +/mnt/sdcard/boot # ln -s vmlinuz-5.8.16-sunxi64 zImage
    +/mnt/sdcard/boot # ln -s uInitrd-5.8.16-sunxi64 uInitrd
    +/mnt/sdcard/boot # ln -s dtb-5.8.16 dtb
    +
    +

    If you upgrade from some very old build, you might need to update your boot script.

    +
      +
    • Note: The following example is for Allwinner boards.
    • +
    +
      +
    • Note: You will need a u-boot-tools package on your host system.
    • +
    +
    Bash Session
    1
    +2
    +3
    /mnt/sdcard/boot # wget https://raw.githubusercontent.com/armbian/build/master/config/bootscripts/boot-sunxi.cmd
    +/mnt/sdcard/boot # mv boot-sunxi.cmd boot.cmd
    +/mnt/sdcard/boot # mkimage -C none -A arm -T script -d boot.cmd boot.scr
    +
    +

    Unmount SD card.

    +
    Bash Session
    1
    +2
    /mnt/sdcard/boot # cd /
    +/ # umount /mnt/sdcard
    +
    +

    Move it to the board and power on. Check serial output for errors if problems persist.

    +

    Flashing boot loader

    +

    Sometimes we need to flash boot loader from some other Linux. Attach an SD card reader with your SD card and proceed this way:

    +
    Bash Session
    1
    +2
    +3
    +4
    +5
    +6
    +7
    /mnt $ cd
    +~ $ mkdir -p tmp/recovery
    +~ $ cd tmp/recovery
    +~ $ wget https://imola.armbian.com/apt/pool/main/l/linux-u-boot-nanopineo2-current/linux-u-boot-current-nanopineo2_20.08.13_arm64.deb
    +~ $ dpkg-deb -x linux-u-boot-current-nanopineo2_20.08.13_arm64.deb pack
    +~ $ source pack/usr/lib/u-boot/platform_install.sh
    +~ $ write_uboot_platform pack/usr/lib/linux-u-boot-nanopineo2-current /dev/XXX # replace XXX with the actual device /dev/sdb
    +
    +

    Move it to the board and power on. Check serial output for errors if problems persist.

    + + + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + + + +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file diff --git a/611/assets/images/favicon.png b/611/assets/images/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..1cf13b9f9d978896599290a74f77d5dbe7d1655c GIT binary patch literal 1870 zcmV-U2eJ5xP)Gc)JR9QMau)O=X#!i9;T z37kk-upj^(fsR36MHs_+1RCI)NNu9}lD0S{B^g8PN?Ww(5|~L#Ng*g{WsqleV}|#l zz8@ri&cTzw_h33bHI+12+kK6WN$h#n5cD8OQt`5kw6p~9H3()bUQ8OS4Q4HTQ=1Ol z_JAocz`fLbT2^{`8n~UAo=#AUOf=SOq4pYkt;XbC&f#7lb$*7=$na!mWCQ`dBQsO0 zLFBSPj*N?#u5&pf2t4XjEGH|=pPQ8xh7tpx;US5Cx_Ju;!O`ya-yF`)b%TEt5>eP1ZX~}sjjA%FJF?h7cX8=b!DZl<6%Cv z*G0uvvU+vmnpLZ2paivG-(cd*y3$hCIcsZcYOGh{$&)A6*XX&kXZd3G8m)G$Zz-LV z^GF3VAW^Mdv!)4OM8EgqRiz~*Cji;uzl2uC9^=8I84vNp;ltJ|q-*uQwGp2ma6cY7 z;`%`!9UXO@fr&Ebapfs34OmS9^u6$)bJxrucutf>`dKPKT%%*d3XlFVKunp9 zasduxjrjs>f8V=D|J=XNZp;_Zy^WgQ$9WDjgY=z@stwiEBm9u5*|34&1Na8BMjjgf3+SHcr`5~>oz1Y?SW^=K z^bTyO6>Gar#P_W2gEMwq)ot3; zREHn~U&Dp0l6YT0&k-wLwYjb?5zGK`W6S2v+K>AM(95m2C20L|3m~rN8dprPr@t)5lsk9Hu*W z?pS990s;Ez=+Rj{x7p``4>+c0G5^pYnB1^!TL=(?HLHZ+HicG{~4F1d^5Awl_2!1jICM-!9eoLhbbT^;yHcefyTAaqRcY zmuctDopPT!%k+}x%lZRKnzykr2}}XfG_ne?nRQO~?%hkzo;@RN{P6o`&mMUWBYMTe z6i8ChtjX&gXl`nvrU>jah)2iNM%JdjqoaeaU%yVn!^70x-flljp6Q5tK}5}&X8&&G zX3fpb3E(!rH=zVI_9Gjl45w@{(ITqngWFe7@9{mX;tO25Z_8 zQHEpI+FkTU#4xu>RkN>b3Tnc3UpWzPXWm#o55GKF09j^Mh~)K7{QqbO_~(@CVq! zS<8954|P8mXN2MRs86xZ&Q4EfM@JB94b=(YGuk)s&^jiSF=t3*oNK3`rD{H`yQ?d; ztE=laAUoZx5?RC8*WKOj`%LXEkgDd>&^Q4M^z`%u0rg-It=hLCVsq!Z%^6eB-OvOT zFZ28TN&cRmgU}Elrnk43)!>Z1FCPL2K$7}gwzIc48NX}#!A1BpJP?#v5wkNprhV** z?Cpalt1oH&{r!o3eSKc&ap)iz2BTn_VV`4>9M^b3;(YY}4>#ML6{~(4mH+?%07*qo IM6N<$f(jP3KmY&$ literal 0 HcmV?d00001 diff --git a/611/assets/javascripts/bundle.60a45f97.min.js b/611/assets/javascripts/bundle.60a45f97.min.js new file mode 100644 index 000000000..f8f18f6cc --- /dev/null +++ b/611/assets/javascripts/bundle.60a45f97.min.js @@ -0,0 +1,16 @@ +"use strict";(()=>{var Wi=Object.create;var gr=Object.defineProperty;var Di=Object.getOwnPropertyDescriptor;var Vi=Object.getOwnPropertyNames,Vt=Object.getOwnPropertySymbols,Ni=Object.getPrototypeOf,yr=Object.prototype.hasOwnProperty,ao=Object.prototype.propertyIsEnumerable;var io=(e,t,r)=>t in e?gr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,$=(e,t)=>{for(var r in t||(t={}))yr.call(t,r)&&io(e,r,t[r]);if(Vt)for(var r of Vt(t))ao.call(t,r)&&io(e,r,t[r]);return e};var so=(e,t)=>{var r={};for(var o in e)yr.call(e,o)&&t.indexOf(o)<0&&(r[o]=e[o]);if(e!=null&&Vt)for(var o of Vt(e))t.indexOf(o)<0&&ao.call(e,o)&&(r[o]=e[o]);return r};var xr=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var zi=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Vi(t))!yr.call(e,n)&&n!==r&&gr(e,n,{get:()=>t[n],enumerable:!(o=Di(t,n))||o.enumerable});return e};var Mt=(e,t,r)=>(r=e!=null?Wi(Ni(e)):{},zi(t||!e||!e.__esModule?gr(r,"default",{value:e,enumerable:!0}):r,e));var co=(e,t,r)=>new Promise((o,n)=>{var i=p=>{try{s(r.next(p))}catch(c){n(c)}},a=p=>{try{s(r.throw(p))}catch(c){n(c)}},s=p=>p.done?o(p.value):Promise.resolve(p.value).then(i,a);s((r=r.apply(e,t)).next())});var lo=xr((Er,po)=>{(function(e,t){typeof Er=="object"&&typeof po!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(Er,function(){"use strict";function e(r){var o=!0,n=!1,i=null,a={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function s(k){return!!(k&&k!==document&&k.nodeName!=="HTML"&&k.nodeName!=="BODY"&&"classList"in k&&"contains"in k.classList)}function p(k){var ft=k.type,qe=k.tagName;return!!(qe==="INPUT"&&a[ft]&&!k.readOnly||qe==="TEXTAREA"&&!k.readOnly||k.isContentEditable)}function c(k){k.classList.contains("focus-visible")||(k.classList.add("focus-visible"),k.setAttribute("data-focus-visible-added",""))}function l(k){k.hasAttribute("data-focus-visible-added")&&(k.classList.remove("focus-visible"),k.removeAttribute("data-focus-visible-added"))}function f(k){k.metaKey||k.altKey||k.ctrlKey||(s(r.activeElement)&&c(r.activeElement),o=!0)}function u(k){o=!1}function d(k){s(k.target)&&(o||p(k.target))&&c(k.target)}function y(k){s(k.target)&&(k.target.classList.contains("focus-visible")||k.target.hasAttribute("data-focus-visible-added"))&&(n=!0,window.clearTimeout(i),i=window.setTimeout(function(){n=!1},100),l(k.target))}function L(k){document.visibilityState==="hidden"&&(n&&(o=!0),X())}function X(){document.addEventListener("mousemove",J),document.addEventListener("mousedown",J),document.addEventListener("mouseup",J),document.addEventListener("pointermove",J),document.addEventListener("pointerdown",J),document.addEventListener("pointerup",J),document.addEventListener("touchmove",J),document.addEventListener("touchstart",J),document.addEventListener("touchend",J)}function te(){document.removeEventListener("mousemove",J),document.removeEventListener("mousedown",J),document.removeEventListener("mouseup",J),document.removeEventListener("pointermove",J),document.removeEventListener("pointerdown",J),document.removeEventListener("pointerup",J),document.removeEventListener("touchmove",J),document.removeEventListener("touchstart",J),document.removeEventListener("touchend",J)}function J(k){k.target.nodeName&&k.target.nodeName.toLowerCase()==="html"||(o=!1,te())}document.addEventListener("keydown",f,!0),document.addEventListener("mousedown",u,!0),document.addEventListener("pointerdown",u,!0),document.addEventListener("touchstart",u,!0),document.addEventListener("visibilitychange",L,!0),X(),r.addEventListener("focus",d,!0),r.addEventListener("blur",y,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var qr=xr((hy,On)=>{"use strict";/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var $a=/["'&<>]/;On.exports=Pa;function Pa(e){var t=""+e,r=$a.exec(t);if(!r)return t;var o,n="",i=0,a=0;for(i=r.index;i{/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */(function(t,r){typeof It=="object"&&typeof Yr=="object"?Yr.exports=r():typeof define=="function"&&define.amd?define([],r):typeof It=="object"?It.ClipboardJS=r():t.ClipboardJS=r()})(It,function(){return function(){var e={686:function(o,n,i){"use strict";i.d(n,{default:function(){return Ui}});var a=i(279),s=i.n(a),p=i(370),c=i.n(p),l=i(817),f=i.n(l);function u(V){try{return document.execCommand(V)}catch(A){return!1}}var d=function(A){var M=f()(A);return u("cut"),M},y=d;function L(V){var A=document.documentElement.getAttribute("dir")==="rtl",M=document.createElement("textarea");M.style.fontSize="12pt",M.style.border="0",M.style.padding="0",M.style.margin="0",M.style.position="absolute",M.style[A?"right":"left"]="-9999px";var F=window.pageYOffset||document.documentElement.scrollTop;return M.style.top="".concat(F,"px"),M.setAttribute("readonly",""),M.value=V,M}var X=function(A,M){var F=L(A);M.container.appendChild(F);var D=f()(F);return u("copy"),F.remove(),D},te=function(A){var M=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},F="";return typeof A=="string"?F=X(A,M):A instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(A==null?void 0:A.type)?F=X(A.value,M):(F=f()(A),u("copy")),F},J=te;function k(V){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?k=function(M){return typeof M}:k=function(M){return M&&typeof Symbol=="function"&&M.constructor===Symbol&&M!==Symbol.prototype?"symbol":typeof M},k(V)}var ft=function(){var A=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},M=A.action,F=M===void 0?"copy":M,D=A.container,Y=A.target,$e=A.text;if(F!=="copy"&&F!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(Y!==void 0)if(Y&&k(Y)==="object"&&Y.nodeType===1){if(F==="copy"&&Y.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(F==="cut"&&(Y.hasAttribute("readonly")||Y.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if($e)return J($e,{container:D});if(Y)return F==="cut"?y(Y):J(Y,{container:D})},qe=ft;function Fe(V){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Fe=function(M){return typeof M}:Fe=function(M){return M&&typeof Symbol=="function"&&M.constructor===Symbol&&M!==Symbol.prototype?"symbol":typeof M},Fe(V)}function ki(V,A){if(!(V instanceof A))throw new TypeError("Cannot call a class as a function")}function no(V,A){for(var M=0;M0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof D.action=="function"?D.action:this.defaultAction,this.target=typeof D.target=="function"?D.target:this.defaultTarget,this.text=typeof D.text=="function"?D.text:this.defaultText,this.container=Fe(D.container)==="object"?D.container:document.body}},{key:"listenClick",value:function(D){var Y=this;this.listener=c()(D,"click",function($e){return Y.onClick($e)})}},{key:"onClick",value:function(D){var Y=D.delegateTarget||D.currentTarget,$e=this.action(Y)||"copy",Dt=qe({action:$e,container:this.container,target:this.target(Y),text:this.text(Y)});this.emit(Dt?"success":"error",{action:$e,text:Dt,trigger:Y,clearSelection:function(){Y&&Y.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(D){return vr("action",D)}},{key:"defaultTarget",value:function(D){var Y=vr("target",D);if(Y)return document.querySelector(Y)}},{key:"defaultText",value:function(D){return vr("text",D)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(D){var Y=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return J(D,Y)}},{key:"cut",value:function(D){return y(D)}},{key:"isSupported",value:function(){var D=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],Y=typeof D=="string"?[D]:D,$e=!!document.queryCommandSupported;return Y.forEach(function(Dt){$e=$e&&!!document.queryCommandSupported(Dt)}),$e}}]),M}(s()),Ui=Fi},828:function(o){var n=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function a(s,p){for(;s&&s.nodeType!==n;){if(typeof s.matches=="function"&&s.matches(p))return s;s=s.parentNode}}o.exports=a},438:function(o,n,i){var a=i(828);function s(l,f,u,d,y){var L=c.apply(this,arguments);return l.addEventListener(u,L,y),{destroy:function(){l.removeEventListener(u,L,y)}}}function p(l,f,u,d,y){return typeof l.addEventListener=="function"?s.apply(null,arguments):typeof u=="function"?s.bind(null,document).apply(null,arguments):(typeof l=="string"&&(l=document.querySelectorAll(l)),Array.prototype.map.call(l,function(L){return s(L,f,u,d,y)}))}function c(l,f,u,d){return function(y){y.delegateTarget=a(y.target,f),y.delegateTarget&&d.call(l,y)}}o.exports=p},879:function(o,n){n.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},n.nodeList=function(i){var a=Object.prototype.toString.call(i);return i!==void 0&&(a==="[object NodeList]"||a==="[object HTMLCollection]")&&"length"in i&&(i.length===0||n.node(i[0]))},n.string=function(i){return typeof i=="string"||i instanceof String},n.fn=function(i){var a=Object.prototype.toString.call(i);return a==="[object Function]"}},370:function(o,n,i){var a=i(879),s=i(438);function p(u,d,y){if(!u&&!d&&!y)throw new Error("Missing required arguments");if(!a.string(d))throw new TypeError("Second argument must be a String");if(!a.fn(y))throw new TypeError("Third argument must be a Function");if(a.node(u))return c(u,d,y);if(a.nodeList(u))return l(u,d,y);if(a.string(u))return f(u,d,y);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function c(u,d,y){return u.addEventListener(d,y),{destroy:function(){u.removeEventListener(d,y)}}}function l(u,d,y){return Array.prototype.forEach.call(u,function(L){L.addEventListener(d,y)}),{destroy:function(){Array.prototype.forEach.call(u,function(L){L.removeEventListener(d,y)})}}}function f(u,d,y){return s(document.body,u,d,y)}o.exports=p},817:function(o){function n(i){var a;if(i.nodeName==="SELECT")i.focus(),a=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var s=i.hasAttribute("readonly");s||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),s||i.removeAttribute("readonly"),a=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var p=window.getSelection(),c=document.createRange();c.selectNodeContents(i),p.removeAllRanges(),p.addRange(c),a=p.toString()}return a}o.exports=n},279:function(o){function n(){}n.prototype={on:function(i,a,s){var p=this.e||(this.e={});return(p[i]||(p[i]=[])).push({fn:a,ctx:s}),this},once:function(i,a,s){var p=this;function c(){p.off(i,c),a.apply(s,arguments)}return c._=a,this.on(i,c,s)},emit:function(i){var a=[].slice.call(arguments,1),s=((this.e||(this.e={}))[i]||[]).slice(),p=0,c=s.length;for(p;p0&&i[i.length-1])&&(c[0]===6||c[0]===2)){r=0;continue}if(c[0]===3&&(!i||c[1]>i[0]&&c[1]=e.length&&(e=void 0),{value:e&&e[o++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function N(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var o=r.call(e),n,i=[],a;try{for(;(t===void 0||t-- >0)&&!(n=o.next()).done;)i.push(n.value)}catch(s){a={error:s}}finally{try{n&&!n.done&&(r=o.return)&&r.call(o)}finally{if(a)throw a.error}}return i}function q(e,t,r){if(r||arguments.length===2)for(var o=0,n=t.length,i;o1||p(d,L)})},y&&(n[d]=y(n[d])))}function p(d,y){try{c(o[d](y))}catch(L){u(i[0][3],L)}}function c(d){d.value instanceof nt?Promise.resolve(d.value.v).then(l,f):u(i[0][2],d)}function l(d){p("next",d)}function f(d){p("throw",d)}function u(d,y){d(y),i.shift(),i.length&&p(i[0][0],i[0][1])}}function uo(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof he=="function"?he(e):e[Symbol.iterator](),r={},o("next"),o("throw"),o("return"),r[Symbol.asyncIterator]=function(){return this},r);function o(i){r[i]=e[i]&&function(a){return new Promise(function(s,p){a=e[i](a),n(s,p,a.done,a.value)})}}function n(i,a,s,p){Promise.resolve(p).then(function(c){i({value:c,done:s})},a)}}function H(e){return typeof e=="function"}function ut(e){var t=function(o){Error.call(o),o.stack=new Error().stack},r=e(t);return r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r}var zt=ut(function(e){return function(r){e(this),this.message=r?r.length+` errors occurred during unsubscription: +`+r.map(function(o,n){return n+1+") "+o.toString()}).join(` + `):"",this.name="UnsubscriptionError",this.errors=r}});function Qe(e,t){if(e){var r=e.indexOf(t);0<=r&&e.splice(r,1)}}var Ue=function(){function e(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}return e.prototype.unsubscribe=function(){var t,r,o,n,i;if(!this.closed){this.closed=!0;var a=this._parentage;if(a)if(this._parentage=null,Array.isArray(a))try{for(var s=he(a),p=s.next();!p.done;p=s.next()){var c=p.value;c.remove(this)}}catch(L){t={error:L}}finally{try{p&&!p.done&&(r=s.return)&&r.call(s)}finally{if(t)throw t.error}}else a.remove(this);var l=this.initialTeardown;if(H(l))try{l()}catch(L){i=L instanceof zt?L.errors:[L]}var f=this._finalizers;if(f){this._finalizers=null;try{for(var u=he(f),d=u.next();!d.done;d=u.next()){var y=d.value;try{ho(y)}catch(L){i=i!=null?i:[],L instanceof zt?i=q(q([],N(i)),N(L.errors)):i.push(L)}}}catch(L){o={error:L}}finally{try{d&&!d.done&&(n=u.return)&&n.call(u)}finally{if(o)throw o.error}}}if(i)throw new zt(i)}},e.prototype.add=function(t){var r;if(t&&t!==this)if(this.closed)ho(t);else{if(t instanceof e){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(r=this._finalizers)!==null&&r!==void 0?r:[]).push(t)}},e.prototype._hasParent=function(t){var r=this._parentage;return r===t||Array.isArray(r)&&r.includes(t)},e.prototype._addParent=function(t){var r=this._parentage;this._parentage=Array.isArray(r)?(r.push(t),r):r?[r,t]:t},e.prototype._removeParent=function(t){var r=this._parentage;r===t?this._parentage=null:Array.isArray(r)&&Qe(r,t)},e.prototype.remove=function(t){var r=this._finalizers;r&&Qe(r,t),t instanceof e&&t._removeParent(this)},e.EMPTY=function(){var t=new e;return t.closed=!0,t}(),e}();var Tr=Ue.EMPTY;function qt(e){return e instanceof Ue||e&&"closed"in e&&H(e.remove)&&H(e.add)&&H(e.unsubscribe)}function ho(e){H(e)?e():e.unsubscribe()}var Pe={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var dt={setTimeout:function(e,t){for(var r=[],o=2;o0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var o=this,n=this,i=n.hasError,a=n.isStopped,s=n.observers;return i||a?Tr:(this.currentObservers=null,s.push(r),new Ue(function(){o.currentObservers=null,Qe(s,r)}))},t.prototype._checkFinalizedStatuses=function(r){var o=this,n=o.hasError,i=o.thrownError,a=o.isStopped;n?r.error(i):a&&r.complete()},t.prototype.asObservable=function(){var r=new j;return r.source=this,r},t.create=function(r,o){return new To(r,o)},t}(j);var To=function(e){oe(t,e);function t(r,o){var n=e.call(this)||this;return n.destination=r,n.source=o,n}return t.prototype.next=function(r){var o,n;(n=(o=this.destination)===null||o===void 0?void 0:o.next)===null||n===void 0||n.call(o,r)},t.prototype.error=function(r){var o,n;(n=(o=this.destination)===null||o===void 0?void 0:o.error)===null||n===void 0||n.call(o,r)},t.prototype.complete=function(){var r,o;(o=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||o===void 0||o.call(r)},t.prototype._subscribe=function(r){var o,n;return(n=(o=this.source)===null||o===void 0?void 0:o.subscribe(r))!==null&&n!==void 0?n:Tr},t}(g);var _r=function(e){oe(t,e);function t(r){var o=e.call(this)||this;return o._value=r,o}return Object.defineProperty(t.prototype,"value",{get:function(){return this.getValue()},enumerable:!1,configurable:!0}),t.prototype._subscribe=function(r){var o=e.prototype._subscribe.call(this,r);return!o.closed&&r.next(this._value),o},t.prototype.getValue=function(){var r=this,o=r.hasError,n=r.thrownError,i=r._value;if(o)throw n;return this._throwIfClosed(),i},t.prototype.next=function(r){e.prototype.next.call(this,this._value=r)},t}(g);var At={now:function(){return(At.delegate||Date).now()},delegate:void 0};var Ct=function(e){oe(t,e);function t(r,o,n){r===void 0&&(r=1/0),o===void 0&&(o=1/0),n===void 0&&(n=At);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=o,i._timestampProvider=n,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=o===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,o),i}return t.prototype.next=function(r){var o=this,n=o.isStopped,i=o._buffer,a=o._infiniteTimeWindow,s=o._timestampProvider,p=o._windowTime;n||(i.push(r),!a&&i.push(s.now()+p)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var o=this._innerSubscribe(r),n=this,i=n._infiniteTimeWindow,a=n._buffer,s=a.slice(),p=0;p0?e.prototype.schedule.call(this,r,o):(this.delay=o,this.state=r,this.scheduler.flush(this),this)},t.prototype.execute=function(r,o){return o>0||this.closed?e.prototype.execute.call(this,r,o):this._execute(r,o)},t.prototype.requestAsyncId=function(r,o,n){return n===void 0&&(n=0),n!=null&&n>0||n==null&&this.delay>0?e.prototype.requestAsyncId.call(this,r,o,n):(r.flush(this),0)},t}(gt);var Lo=function(e){oe(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t}(yt);var kr=new Lo(Oo);var Mo=function(e){oe(t,e);function t(r,o){var n=e.call(this,r,o)||this;return n.scheduler=r,n.work=o,n}return t.prototype.requestAsyncId=function(r,o,n){return n===void 0&&(n=0),n!==null&&n>0?e.prototype.requestAsyncId.call(this,r,o,n):(r.actions.push(this),r._scheduled||(r._scheduled=vt.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,o,n){var i;if(n===void 0&&(n=0),n!=null?n>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,o,n);var a=r.actions;o!=null&&((i=a[a.length-1])===null||i===void 0?void 0:i.id)!==o&&(vt.cancelAnimationFrame(o),r._scheduled=void 0)},t}(gt);var _o=function(e){oe(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var o=this._scheduled;this._scheduled=void 0;var n=this.actions,i;r=r||n.shift();do if(i=r.execute(r.state,r.delay))break;while((r=n[0])&&r.id===o&&n.shift());if(this._active=!1,i){for(;(r=n[0])&&r.id===o&&n.shift();)r.unsubscribe();throw i}},t}(yt);var me=new _o(Mo);var S=new j(function(e){return e.complete()});function Yt(e){return e&&H(e.schedule)}function Hr(e){return e[e.length-1]}function Xe(e){return H(Hr(e))?e.pop():void 0}function ke(e){return Yt(Hr(e))?e.pop():void 0}function Bt(e,t){return typeof Hr(e)=="number"?e.pop():t}var xt=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function Gt(e){return H(e==null?void 0:e.then)}function Jt(e){return H(e[bt])}function Xt(e){return Symbol.asyncIterator&&H(e==null?void 0:e[Symbol.asyncIterator])}function Zt(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function Zi(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var er=Zi();function tr(e){return H(e==null?void 0:e[er])}function rr(e){return fo(this,arguments,function(){var r,o,n,i;return Nt(this,function(a){switch(a.label){case 0:r=e.getReader(),a.label=1;case 1:a.trys.push([1,,9,10]),a.label=2;case 2:return[4,nt(r.read())];case 3:return o=a.sent(),n=o.value,i=o.done,i?[4,nt(void 0)]:[3,5];case 4:return[2,a.sent()];case 5:return[4,nt(n)];case 6:return[4,a.sent()];case 7:return a.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function or(e){return H(e==null?void 0:e.getReader)}function U(e){if(e instanceof j)return e;if(e!=null){if(Jt(e))return ea(e);if(xt(e))return ta(e);if(Gt(e))return ra(e);if(Xt(e))return Ao(e);if(tr(e))return oa(e);if(or(e))return na(e)}throw Zt(e)}function ea(e){return new j(function(t){var r=e[bt]();if(H(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function ta(e){return new j(function(t){for(var r=0;r=2;return function(o){return o.pipe(e?b(function(n,i){return e(n,i,o)}):le,Te(1),r?De(t):Qo(function(){return new ir}))}}function jr(e){return e<=0?function(){return S}:E(function(t,r){var o=[];t.subscribe(T(r,function(n){o.push(n),e=2,!0))}function pe(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new g}:t,o=e.resetOnError,n=o===void 0?!0:o,i=e.resetOnComplete,a=i===void 0?!0:i,s=e.resetOnRefCountZero,p=s===void 0?!0:s;return function(c){var l,f,u,d=0,y=!1,L=!1,X=function(){f==null||f.unsubscribe(),f=void 0},te=function(){X(),l=u=void 0,y=L=!1},J=function(){var k=l;te(),k==null||k.unsubscribe()};return E(function(k,ft){d++,!L&&!y&&X();var qe=u=u!=null?u:r();ft.add(function(){d--,d===0&&!L&&!y&&(f=Ur(J,p))}),qe.subscribe(ft),!l&&d>0&&(l=new at({next:function(Fe){return qe.next(Fe)},error:function(Fe){L=!0,X(),f=Ur(te,n,Fe),qe.error(Fe)},complete:function(){y=!0,X(),f=Ur(te,a),qe.complete()}}),U(k).subscribe(l))})(c)}}function Ur(e,t){for(var r=[],o=2;oe.next(document)),e}function P(e,t=document){return Array.from(t.querySelectorAll(e))}function R(e,t=document){let r=fe(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function fe(e,t=document){return t.querySelector(e)||void 0}function Ie(){var e,t,r,o;return(o=(r=(t=(e=document.activeElement)==null?void 0:e.shadowRoot)==null?void 0:t.activeElement)!=null?r:document.activeElement)!=null?o:void 0}var wa=O(h(document.body,"focusin"),h(document.body,"focusout")).pipe(_e(1),Q(void 0),m(()=>Ie()||document.body),G(1));function et(e){return wa.pipe(m(t=>e.contains(t)),K())}function $t(e,t){return C(()=>O(h(e,"mouseenter").pipe(m(()=>!0)),h(e,"mouseleave").pipe(m(()=>!1))).pipe(t?Ht(r=>Le(+!r*t)):le,Q(e.matches(":hover"))))}function Jo(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)Jo(e,r)}function x(e,t,...r){let o=document.createElement(e);if(t)for(let n of Object.keys(t))typeof t[n]!="undefined"&&(typeof t[n]!="boolean"?o.setAttribute(n,t[n]):o.setAttribute(n,""));for(let n of r)Jo(o,n);return o}function sr(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function Tt(e){let t=x("script",{src:e});return C(()=>(document.head.appendChild(t),O(h(t,"load"),h(t,"error").pipe(v(()=>$r(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(m(()=>{}),_(()=>document.head.removeChild(t)),Te(1))))}var Xo=new g,Ta=C(()=>typeof ResizeObserver=="undefined"?Tt("https://unpkg.com/resize-observer-polyfill"):I(void 0)).pipe(m(()=>new ResizeObserver(e=>e.forEach(t=>Xo.next(t)))),v(e=>O(Ye,I(e)).pipe(_(()=>e.disconnect()))),G(1));function ce(e){return{width:e.offsetWidth,height:e.offsetHeight}}function ge(e){let t=e;for(;t.clientWidth===0&&t.parentElement;)t=t.parentElement;return Ta.pipe(w(r=>r.observe(t)),v(r=>Xo.pipe(b(o=>o.target===t),_(()=>r.unobserve(t)))),m(()=>ce(e)),Q(ce(e)))}function St(e){return{width:e.scrollWidth,height:e.scrollHeight}}function cr(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}function Zo(e){let t=[],r=e.parentElement;for(;r;)(e.clientWidth>r.clientWidth||e.clientHeight>r.clientHeight)&&t.push(r),r=(e=r).parentElement;return t.length===0&&t.push(document.documentElement),t}function Ve(e){return{x:e.offsetLeft,y:e.offsetTop}}function en(e){let t=e.getBoundingClientRect();return{x:t.x+window.scrollX,y:t.y+window.scrollY}}function tn(e){return O(h(window,"load"),h(window,"resize")).pipe(Me(0,me),m(()=>Ve(e)),Q(Ve(e)))}function pr(e){return{x:e.scrollLeft,y:e.scrollTop}}function Ne(e){return O(h(e,"scroll"),h(window,"scroll"),h(window,"resize")).pipe(Me(0,me),m(()=>pr(e)),Q(pr(e)))}var rn=new g,Sa=C(()=>I(new IntersectionObserver(e=>{for(let t of e)rn.next(t)},{threshold:0}))).pipe(v(e=>O(Ye,I(e)).pipe(_(()=>e.disconnect()))),G(1));function tt(e){return Sa.pipe(w(t=>t.observe(e)),v(t=>rn.pipe(b(({target:r})=>r===e),_(()=>t.unobserve(e)),m(({isIntersecting:r})=>r))))}function on(e,t=16){return Ne(e).pipe(m(({y:r})=>{let o=ce(e),n=St(e);return r>=n.height-o.height-t}),K())}var lr={drawer:R("[data-md-toggle=drawer]"),search:R("[data-md-toggle=search]")};function nn(e){return lr[e].checked}function Je(e,t){lr[e].checked!==t&&lr[e].click()}function ze(e){let t=lr[e];return h(t,"change").pipe(m(()=>t.checked),Q(t.checked))}function Oa(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function La(){return O(h(window,"compositionstart").pipe(m(()=>!0)),h(window,"compositionend").pipe(m(()=>!1))).pipe(Q(!1))}function an(){let e=h(window,"keydown").pipe(b(t=>!(t.metaKey||t.ctrlKey)),m(t=>({mode:nn("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),b(({mode:t,type:r})=>{if(t==="global"){let o=Ie();if(typeof o!="undefined")return!Oa(o,r)}return!0}),pe());return La().pipe(v(t=>t?S:e))}function ye(){return new URL(location.href)}function lt(e,t=!1){if(B("navigation.instant")&&!t){let r=x("a",{href:e.href});document.body.appendChild(r),r.click(),r.remove()}else location.href=e.href}function sn(){return new g}function cn(){return location.hash.slice(1)}function pn(e){let t=x("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function Ma(e){return O(h(window,"hashchange"),e).pipe(m(cn),Q(cn()),b(t=>t.length>0),G(1))}function ln(e){return Ma(e).pipe(m(t=>fe(`[id="${t}"]`)),b(t=>typeof t!="undefined"))}function Pt(e){let t=matchMedia(e);return ar(r=>t.addListener(()=>r(t.matches))).pipe(Q(t.matches))}function mn(){let e=matchMedia("print");return O(h(window,"beforeprint").pipe(m(()=>!0)),h(window,"afterprint").pipe(m(()=>!1))).pipe(Q(e.matches))}function Nr(e,t){return e.pipe(v(r=>r?t():S))}function zr(e,t){return new j(r=>{let o=new XMLHttpRequest;return o.open("GET",`${e}`),o.responseType="blob",o.addEventListener("load",()=>{o.status>=200&&o.status<300?(r.next(o.response),r.complete()):r.error(new Error(o.statusText))}),o.addEventListener("error",()=>{r.error(new Error("Network error"))}),o.addEventListener("abort",()=>{r.complete()}),typeof(t==null?void 0:t.progress$)!="undefined"&&(o.addEventListener("progress",n=>{var i;if(n.lengthComputable)t.progress$.next(n.loaded/n.total*100);else{let a=(i=o.getResponseHeader("Content-Length"))!=null?i:0;t.progress$.next(n.loaded/+a*100)}}),t.progress$.next(5)),o.send(),()=>o.abort()})}function je(e,t){return zr(e,t).pipe(v(r=>r.text()),m(r=>JSON.parse(r)),G(1))}function fn(e,t){let r=new DOMParser;return zr(e,t).pipe(v(o=>o.text()),m(o=>r.parseFromString(o,"text/html")),G(1))}function un(e,t){let r=new DOMParser;return zr(e,t).pipe(v(o=>o.text()),m(o=>r.parseFromString(o,"text/xml")),G(1))}function dn(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function hn(){return O(h(window,"scroll",{passive:!0}),h(window,"resize",{passive:!0})).pipe(m(dn),Q(dn()))}function bn(){return{width:innerWidth,height:innerHeight}}function vn(){return h(window,"resize",{passive:!0}).pipe(m(bn),Q(bn()))}function gn(){return z([hn(),vn()]).pipe(m(([e,t])=>({offset:e,size:t})),G(1))}function mr(e,{viewport$:t,header$:r}){let o=t.pipe(ee("size")),n=z([o,r]).pipe(m(()=>Ve(e)));return z([r,t,n]).pipe(m(([{height:i},{offset:a,size:s},{x:p,y:c}])=>({offset:{x:a.x-p,y:a.y-c+i},size:s})))}function _a(e){return h(e,"message",t=>t.data)}function Aa(e){let t=new g;return t.subscribe(r=>e.postMessage(r)),t}function yn(e,t=new Worker(e)){let r=_a(t),o=Aa(t),n=new g;n.subscribe(o);let i=o.pipe(Z(),ie(!0));return n.pipe(Z(),Re(r.pipe(W(i))),pe())}var Ca=R("#__config"),Ot=JSON.parse(Ca.textContent);Ot.base=`${new URL(Ot.base,ye())}`;function xe(){return Ot}function B(e){return Ot.features.includes(e)}function Ee(e,t){return typeof t!="undefined"?Ot.translations[e].replace("#",t.toString()):Ot.translations[e]}function Se(e,t=document){return R(`[data-md-component=${e}]`,t)}function ae(e,t=document){return P(`[data-md-component=${e}]`,t)}function ka(e){let t=R(".md-typeset > :first-child",e);return h(t,"click",{once:!0}).pipe(m(()=>R(".md-typeset",e)),m(r=>({hash:__md_hash(r.innerHTML)})))}function xn(e){if(!B("announce.dismiss")||!e.childElementCount)return S;if(!e.hidden){let t=R(".md-typeset",e);__md_hash(t.innerHTML)===__md_get("__announce")&&(e.hidden=!0)}return C(()=>{let t=new g;return t.subscribe(({hash:r})=>{e.hidden=!0,__md_set("__announce",r)}),ka(e).pipe(w(r=>t.next(r)),_(()=>t.complete()),m(r=>$({ref:e},r)))})}function Ha(e,{target$:t}){return t.pipe(m(r=>({hidden:r!==e})))}function En(e,t){let r=new g;return r.subscribe(({hidden:o})=>{e.hidden=o}),Ha(e,t).pipe(w(o=>r.next(o)),_(()=>r.complete()),m(o=>$({ref:e},o)))}function Rt(e,t){return t==="inline"?x("div",{class:"md-tooltip md-tooltip--inline",id:e,role:"tooltip"},x("div",{class:"md-tooltip__inner md-typeset"})):x("div",{class:"md-tooltip",id:e,role:"tooltip"},x("div",{class:"md-tooltip__inner md-typeset"}))}function wn(...e){return x("div",{class:"md-tooltip2",role:"tooltip"},x("div",{class:"md-tooltip2__inner md-typeset"},e))}function Tn(e,t){if(t=t?`${t}_annotation_${e}`:void 0,t){let r=t?`#${t}`:void 0;return x("aside",{class:"md-annotation",tabIndex:0},Rt(t),x("a",{href:r,class:"md-annotation__index",tabIndex:-1},x("span",{"data-md-annotation-id":e})))}else return x("aside",{class:"md-annotation",tabIndex:0},Rt(t),x("span",{class:"md-annotation__index",tabIndex:-1},x("span",{"data-md-annotation-id":e})))}function Sn(e){return x("button",{class:"md-clipboard md-icon",title:Ee("clipboard.copy"),"data-clipboard-target":`#${e} > code`})}var Ln=Mt(qr());function Qr(e,t){let r=t&2,o=t&1,n=Object.keys(e.terms).filter(p=>!e.terms[p]).reduce((p,c)=>[...p,x("del",null,(0,Ln.default)(c))," "],[]).slice(0,-1),i=xe(),a=new URL(e.location,i.base);B("search.highlight")&&a.searchParams.set("h",Object.entries(e.terms).filter(([,p])=>p).reduce((p,[c])=>`${p} ${c}`.trim(),""));let{tags:s}=xe();return x("a",{href:`${a}`,class:"md-search-result__link",tabIndex:-1},x("article",{class:"md-search-result__article md-typeset","data-md-score":e.score.toFixed(2)},r>0&&x("div",{class:"md-search-result__icon md-icon"}),r>0&&x("h1",null,e.title),r<=0&&x("h2",null,e.title),o>0&&e.text.length>0&&e.text,e.tags&&x("nav",{class:"md-tags"},e.tags.map(p=>{let c=s?p in s?`md-tag-icon md-tag--${s[p]}`:"md-tag-icon":"";return x("span",{class:`md-tag ${c}`},p)})),o>0&&n.length>0&&x("p",{class:"md-search-result__terms"},Ee("search.result.term.missing"),": ",...n)))}function Mn(e){let t=e[0].score,r=[...e],o=xe(),n=r.findIndex(l=>!`${new URL(l.location,o.base)}`.includes("#")),[i]=r.splice(n,1),a=r.findIndex(l=>l.scoreQr(l,1)),...p.length?[x("details",{class:"md-search-result__more"},x("summary",{tabIndex:-1},x("div",null,p.length>0&&p.length===1?Ee("search.result.more.one"):Ee("search.result.more.other",p.length))),...p.map(l=>Qr(l,1)))]:[]];return x("li",{class:"md-search-result__item"},c)}function _n(e){return x("ul",{class:"md-source__facts"},Object.entries(e).map(([t,r])=>x("li",{class:`md-source__fact md-source__fact--${t}`},typeof r=="number"?sr(r):r)))}function Kr(e){let t=`tabbed-control tabbed-control--${e}`;return x("div",{class:t,hidden:!0},x("button",{class:"tabbed-button",tabIndex:-1,"aria-hidden":"true"}))}function An(e){return x("div",{class:"md-typeset__scrollwrap"},x("div",{class:"md-typeset__table"},e))}function Ra(e){var o;let t=xe(),r=new URL(`../${e.version}/`,t.base);return x("li",{class:"md-version__item"},x("a",{href:`${r}`,class:"md-version__link"},e.title,((o=t.version)==null?void 0:o.alias)&&e.aliases.length>0&&x("span",{class:"md-version__alias"},e.aliases[0])))}function Cn(e,t){var o;let r=xe();return e=e.filter(n=>{var i;return!((i=n.properties)!=null&&i.hidden)}),x("div",{class:"md-version"},x("button",{class:"md-version__current","aria-label":Ee("select.version")},t.title,((o=r.version)==null?void 0:o.alias)&&t.aliases.length>0&&x("span",{class:"md-version__alias"},t.aliases[0])),x("ul",{class:"md-version__list"},e.map(Ra)))}var Ia=0;function ja(e){let t=z([et(e),$t(e)]).pipe(m(([o,n])=>o||n),K()),r=C(()=>Zo(e)).pipe(ne(Ne),pt(1),He(t),m(()=>en(e)));return t.pipe(Ae(o=>o),v(()=>z([t,r])),m(([o,n])=>({active:o,offset:n})),pe())}function Fa(e,t){let{content$:r,viewport$:o}=t,n=`__tooltip2_${Ia++}`;return C(()=>{let i=new g,a=new _r(!1);i.pipe(Z(),ie(!1)).subscribe(a);let s=a.pipe(Ht(c=>Le(+!c*250,kr)),K(),v(c=>c?r:S),w(c=>c.id=n),pe());z([i.pipe(m(({active:c})=>c)),s.pipe(v(c=>$t(c,250)),Q(!1))]).pipe(m(c=>c.some(l=>l))).subscribe(a);let p=a.pipe(b(c=>c),re(s,o),m(([c,l,{size:f}])=>{let u=e.getBoundingClientRect(),d=u.width/2;if(l.role==="tooltip")return{x:d,y:8+u.height};if(u.y>=f.height/2){let{height:y}=ce(l);return{x:d,y:-16-y}}else return{x:d,y:16+u.height}}));return z([s,i,p]).subscribe(([c,{offset:l},f])=>{c.style.setProperty("--md-tooltip-host-x",`${l.x}px`),c.style.setProperty("--md-tooltip-host-y",`${l.y}px`),c.style.setProperty("--md-tooltip-x",`${f.x}px`),c.style.setProperty("--md-tooltip-y",`${f.y}px`),c.classList.toggle("md-tooltip2--top",f.y<0),c.classList.toggle("md-tooltip2--bottom",f.y>=0)}),a.pipe(b(c=>c),re(s,(c,l)=>l),b(c=>c.role==="tooltip")).subscribe(c=>{let l=ce(R(":scope > *",c));c.style.setProperty("--md-tooltip-width",`${l.width}px`),c.style.setProperty("--md-tooltip-tail","0px")}),a.pipe(K(),ve(me),re(s)).subscribe(([c,l])=>{l.classList.toggle("md-tooltip2--active",c)}),z([a.pipe(b(c=>c)),s]).subscribe(([c,l])=>{l.role==="dialog"?(e.setAttribute("aria-controls",n),e.setAttribute("aria-haspopup","dialog")):e.setAttribute("aria-describedby",n)}),a.pipe(b(c=>!c)).subscribe(()=>{e.removeAttribute("aria-controls"),e.removeAttribute("aria-describedby"),e.removeAttribute("aria-haspopup")}),ja(e).pipe(w(c=>i.next(c)),_(()=>i.complete()),m(c=>$({ref:e},c)))})}function mt(e,{viewport$:t},r=document.body){return Fa(e,{content$:new j(o=>{let n=e.title,i=wn(n);return o.next(i),e.removeAttribute("title"),r.append(i),()=>{i.remove(),e.setAttribute("title",n)}}),viewport$:t})}function Ua(e,t){let r=C(()=>z([tn(e),Ne(t)])).pipe(m(([{x:o,y:n},i])=>{let{width:a,height:s}=ce(e);return{x:o-i.x+a/2,y:n-i.y+s/2}}));return et(e).pipe(v(o=>r.pipe(m(n=>({active:o,offset:n})),Te(+!o||1/0))))}function kn(e,t,{target$:r}){let[o,n]=Array.from(e.children);return C(()=>{let i=new g,a=i.pipe(Z(),ie(!0));return i.subscribe({next({offset:s}){e.style.setProperty("--md-tooltip-x",`${s.x}px`),e.style.setProperty("--md-tooltip-y",`${s.y}px`)},complete(){e.style.removeProperty("--md-tooltip-x"),e.style.removeProperty("--md-tooltip-y")}}),tt(e).pipe(W(a)).subscribe(s=>{e.toggleAttribute("data-md-visible",s)}),O(i.pipe(b(({active:s})=>s)),i.pipe(_e(250),b(({active:s})=>!s))).subscribe({next({active:s}){s?e.prepend(o):o.remove()},complete(){e.prepend(o)}}),i.pipe(Me(16,me)).subscribe(({active:s})=>{o.classList.toggle("md-tooltip--active",s)}),i.pipe(pt(125,me),b(()=>!!e.offsetParent),m(()=>e.offsetParent.getBoundingClientRect()),m(({x:s})=>s)).subscribe({next(s){s?e.style.setProperty("--md-tooltip-0",`${-s}px`):e.style.removeProperty("--md-tooltip-0")},complete(){e.style.removeProperty("--md-tooltip-0")}}),h(n,"click").pipe(W(a),b(s=>!(s.metaKey||s.ctrlKey))).subscribe(s=>{s.stopPropagation(),s.preventDefault()}),h(n,"mousedown").pipe(W(a),re(i)).subscribe(([s,{active:p}])=>{var c;if(s.button!==0||s.metaKey||s.ctrlKey)s.preventDefault();else if(p){s.preventDefault();let l=e.parentElement.closest(".md-annotation");l instanceof HTMLElement?l.focus():(c=Ie())==null||c.blur()}}),r.pipe(W(a),b(s=>s===o),Ge(125)).subscribe(()=>e.focus()),Ua(e,t).pipe(w(s=>i.next(s)),_(()=>i.complete()),m(s=>$({ref:e},s)))})}function Wa(e){return e.tagName==="CODE"?P(".c, .c1, .cm",e):[e]}function Da(e){let t=[];for(let r of Wa(e)){let o=[],n=document.createNodeIterator(r,NodeFilter.SHOW_TEXT);for(let i=n.nextNode();i;i=n.nextNode())o.push(i);for(let i of o){let a;for(;a=/(\(\d+\))(!)?/.exec(i.textContent);){let[,s,p]=a;if(typeof p=="undefined"){let c=i.splitText(a.index);i=c.splitText(s.length),t.push(c)}else{i.textContent=s,t.push(i);break}}}}return t}function Hn(e,t){t.append(...Array.from(e.childNodes))}function fr(e,t,{target$:r,print$:o}){let n=t.closest("[id]"),i=n==null?void 0:n.id,a=new Map;for(let s of Da(t)){let[,p]=s.textContent.match(/\((\d+)\)/);fe(`:scope > li:nth-child(${p})`,e)&&(a.set(p,Tn(p,i)),s.replaceWith(a.get(p)))}return a.size===0?S:C(()=>{let s=new g,p=s.pipe(Z(),ie(!0)),c=[];for(let[l,f]of a)c.push([R(".md-typeset",f),R(`:scope > li:nth-child(${l})`,e)]);return o.pipe(W(p)).subscribe(l=>{e.hidden=!l,e.classList.toggle("md-annotation-list",l);for(let[f,u]of c)l?Hn(f,u):Hn(u,f)}),O(...[...a].map(([,l])=>kn(l,t,{target$:r}))).pipe(_(()=>s.complete()),pe())})}function $n(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return $n(t)}}function Pn(e,t){return C(()=>{let r=$n(e);return typeof r!="undefined"?fr(r,e,t):S})}var Rn=Mt(Br());var Va=0;function In(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return In(t)}}function Na(e){return ge(e).pipe(m(({width:t})=>({scrollable:St(e).width>t})),ee("scrollable"))}function jn(e,t){let{matches:r}=matchMedia("(hover)"),o=C(()=>{let n=new g,i=n.pipe(jr(1));n.subscribe(({scrollable:c})=>{c&&r?e.setAttribute("tabindex","0"):e.removeAttribute("tabindex")});let a=[];if(Rn.default.isSupported()&&(e.closest(".copy")||B("content.code.copy")&&!e.closest(".no-copy"))){let c=e.closest("pre");c.id=`__code_${Va++}`;let l=Sn(c.id);c.insertBefore(l,e),B("content.tooltips")&&a.push(mt(l,{viewport$}))}let s=e.closest(".highlight");if(s instanceof HTMLElement){let c=In(s);if(typeof c!="undefined"&&(s.classList.contains("annotate")||B("content.code.annotate"))){let l=fr(c,e,t);a.push(ge(s).pipe(W(i),m(({width:f,height:u})=>f&&u),K(),v(f=>f?l:S)))}}return P(":scope > span[id]",e).length&&e.classList.add("md-code__content"),Na(e).pipe(w(c=>n.next(c)),_(()=>n.complete()),m(c=>$({ref:e},c)),Re(...a))});return B("content.lazy")?tt(e).pipe(b(n=>n),Te(1),v(()=>o)):o}function za(e,{target$:t,print$:r}){let o=!0;return O(t.pipe(m(n=>n.closest("details:not([open])")),b(n=>e===n),m(()=>({action:"open",reveal:!0}))),r.pipe(b(n=>n||!o),w(()=>o=e.open),m(n=>({action:n?"open":"close"}))))}function Fn(e,t){return C(()=>{let r=new g;return r.subscribe(({action:o,reveal:n})=>{e.toggleAttribute("open",o==="open"),n&&e.scrollIntoView()}),za(e,t).pipe(w(o=>r.next(o)),_(()=>r.complete()),m(o=>$({ref:e},o)))})}var Un=".node circle,.node ellipse,.node path,.node polygon,.node rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}marker{fill:var(--md-mermaid-edge-color)!important}.edgeLabel .label rect{fill:#0000}.flowchartTitleText{fill:var(--md-mermaid-label-fg-color)}.label{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.label foreignObject{line-height:normal;overflow:visible}.label div .edgeLabel{color:var(--md-mermaid-label-fg-color)}.edgeLabel,.edgeLabel p,.label div .edgeLabel{background-color:var(--md-mermaid-label-bg-color)}.edgeLabel,.edgeLabel p{fill:var(--md-mermaid-label-bg-color);color:var(--md-mermaid-edge-color)}.edgePath .path,.flowchart-link{stroke:var(--md-mermaid-edge-color);stroke-width:.05rem}.edgePath .arrowheadPath{fill:var(--md-mermaid-edge-color);stroke:none}.cluster rect{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}.cluster span{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}g #flowchart-circleEnd,g #flowchart-circleStart,g #flowchart-crossEnd,g #flowchart-crossStart,g #flowchart-pointEnd,g #flowchart-pointStart{stroke:none}.classDiagramTitleText{fill:var(--md-mermaid-label-fg-color)}g.classGroup line,g.classGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.classGroup text{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.classLabel .box{fill:var(--md-mermaid-label-bg-color);background-color:var(--md-mermaid-label-bg-color);opacity:1}.classLabel .label{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.node .divider{stroke:var(--md-mermaid-node-fg-color)}.relation{stroke:var(--md-mermaid-edge-color)}.cardinality{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.cardinality text{fill:inherit!important}defs #classDiagram-compositionEnd,defs #classDiagram-compositionStart,defs #classDiagram-dependencyEnd,defs #classDiagram-dependencyStart,defs #classDiagram-extensionEnd,defs #classDiagram-extensionStart{fill:var(--md-mermaid-edge-color)!important;stroke:var(--md-mermaid-edge-color)!important}defs #classDiagram-aggregationEnd,defs #classDiagram-aggregationStart{fill:var(--md-mermaid-label-bg-color)!important;stroke:var(--md-mermaid-edge-color)!important}.statediagramTitleText{fill:var(--md-mermaid-label-fg-color)}g.stateGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.stateGroup .state-title{fill:var(--md-mermaid-label-fg-color)!important;font-family:var(--md-mermaid-font-family)}g.stateGroup .composit{fill:var(--md-mermaid-label-bg-color)}.nodeLabel,.nodeLabel p{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}a .nodeLabel{text-decoration:underline}.node circle.state-end,.node circle.state-start,.start-state{fill:var(--md-mermaid-edge-color);stroke:none}.end-state-inner,.end-state-outer{fill:var(--md-mermaid-edge-color)}.end-state-inner,.node circle.state-end{stroke:var(--md-mermaid-label-bg-color)}.transition{stroke:var(--md-mermaid-edge-color)}[id^=state-fork] rect,[id^=state-join] rect{fill:var(--md-mermaid-edge-color)!important;stroke:none!important}.statediagram-cluster.statediagram-cluster .inner{fill:var(--md-default-bg-color)}.statediagram-cluster rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}.statediagram-state rect.divider{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}defs #statediagram-barbEnd{stroke:var(--md-mermaid-edge-color)}.entityTitleText{fill:var(--md-mermaid-label-fg-color)}.attributeBoxEven,.attributeBoxOdd{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}.entityBox{fill:var(--md-mermaid-label-bg-color);stroke:var(--md-mermaid-node-fg-color)}.entityLabel{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.relationshipLabelBox{fill:var(--md-mermaid-label-bg-color);fill-opacity:1;background-color:var(--md-mermaid-label-bg-color);opacity:1}.relationshipLabel{fill:var(--md-mermaid-label-fg-color)}.relationshipLine{stroke:var(--md-mermaid-edge-color)}defs #ONE_OR_MORE_END *,defs #ONE_OR_MORE_START *,defs #ONLY_ONE_END *,defs #ONLY_ONE_START *,defs #ZERO_OR_MORE_END *,defs #ZERO_OR_MORE_START *,defs #ZERO_OR_ONE_END *,defs #ZERO_OR_ONE_START *{stroke:var(--md-mermaid-edge-color)!important}defs #ZERO_OR_MORE_END circle,defs #ZERO_OR_MORE_START circle{fill:var(--md-mermaid-label-bg-color)}text:not([class]):last-child{fill:var(--md-mermaid-label-fg-color)}.actor{fill:var(--md-mermaid-sequence-actor-bg-color);stroke:var(--md-mermaid-sequence-actor-border-color)}text.actor>tspan{fill:var(--md-mermaid-sequence-actor-fg-color);font-family:var(--md-mermaid-font-family)}line{stroke:var(--md-mermaid-sequence-actor-line-color)}.actor-man circle,.actor-man line{fill:var(--md-mermaid-sequence-actorman-bg-color);stroke:var(--md-mermaid-sequence-actorman-line-color)}.messageLine0,.messageLine1{stroke:var(--md-mermaid-sequence-message-line-color)}.note{fill:var(--md-mermaid-sequence-note-bg-color);stroke:var(--md-mermaid-sequence-note-border-color)}.loopText,.loopText>tspan,.messageText,.noteText>tspan{stroke:none;font-family:var(--md-mermaid-font-family)!important}.messageText{fill:var(--md-mermaid-sequence-message-fg-color)}.loopText,.loopText>tspan{fill:var(--md-mermaid-sequence-loop-fg-color)}.noteText>tspan{fill:var(--md-mermaid-sequence-note-fg-color)}#arrowhead path{fill:var(--md-mermaid-sequence-message-line-color);stroke:none}.loopLine{fill:var(--md-mermaid-sequence-loop-bg-color);stroke:var(--md-mermaid-sequence-loop-border-color)}.labelBox{fill:var(--md-mermaid-sequence-label-bg-color);stroke:none}.labelText,.labelText>span{fill:var(--md-mermaid-sequence-label-fg-color);font-family:var(--md-mermaid-font-family)}.sequenceNumber{fill:var(--md-mermaid-sequence-number-fg-color)}rect.rect{fill:var(--md-mermaid-sequence-box-bg-color);stroke:none}rect.rect+text.text{fill:var(--md-mermaid-sequence-box-fg-color)}defs #sequencenumber{fill:var(--md-mermaid-sequence-number-bg-color)!important}";var Gr,Qa=0;function Ka(){return typeof mermaid=="undefined"||mermaid instanceof Element?Tt("https://unpkg.com/mermaid@11/dist/mermaid.min.js"):I(void 0)}function Wn(e){return e.classList.remove("mermaid"),Gr||(Gr=Ka().pipe(w(()=>mermaid.initialize({startOnLoad:!1,themeCSS:Un,sequence:{actorFontSize:"16px",messageFontSize:"16px",noteFontSize:"16px"}})),m(()=>{}),G(1))),Gr.subscribe(()=>co(this,null,function*(){e.classList.add("mermaid");let t=`__mermaid_${Qa++}`,r=x("div",{class:"mermaid"}),o=e.textContent,{svg:n,fn:i}=yield mermaid.render(t,o),a=r.attachShadow({mode:"closed"});a.innerHTML=n,e.replaceWith(r),i==null||i(a)})),Gr.pipe(m(()=>({ref:e})))}var Dn=x("table");function Vn(e){return e.replaceWith(Dn),Dn.replaceWith(An(e)),I({ref:e})}function Ya(e){let t=e.find(r=>r.checked)||e[0];return O(...e.map(r=>h(r,"change").pipe(m(()=>R(`label[for="${r.id}"]`))))).pipe(Q(R(`label[for="${t.id}"]`)),m(r=>({active:r})))}function Nn(e,{viewport$:t,target$:r}){let o=R(".tabbed-labels",e),n=P(":scope > input",e),i=Kr("prev");e.append(i);let a=Kr("next");return e.append(a),C(()=>{let s=new g,p=s.pipe(Z(),ie(!0));z([s,ge(e),tt(e)]).pipe(W(p),Me(1,me)).subscribe({next([{active:c},l]){let f=Ve(c),{width:u}=ce(c);e.style.setProperty("--md-indicator-x",`${f.x}px`),e.style.setProperty("--md-indicator-width",`${u}px`);let d=pr(o);(f.xd.x+l.width)&&o.scrollTo({left:Math.max(0,f.x-16),behavior:"smooth"})},complete(){e.style.removeProperty("--md-indicator-x"),e.style.removeProperty("--md-indicator-width")}}),z([Ne(o),ge(o)]).pipe(W(p)).subscribe(([c,l])=>{let f=St(o);i.hidden=c.x<16,a.hidden=c.x>f.width-l.width-16}),O(h(i,"click").pipe(m(()=>-1)),h(a,"click").pipe(m(()=>1))).pipe(W(p)).subscribe(c=>{let{width:l}=ce(o);o.scrollBy({left:l*c,behavior:"smooth"})}),r.pipe(W(p),b(c=>n.includes(c))).subscribe(c=>c.click()),o.classList.add("tabbed-labels--linked");for(let c of n){let l=R(`label[for="${c.id}"]`);l.replaceChildren(x("a",{href:`#${l.htmlFor}`,tabIndex:-1},...Array.from(l.childNodes))),h(l.firstElementChild,"click").pipe(W(p),b(f=>!(f.metaKey||f.ctrlKey)),w(f=>{f.preventDefault(),f.stopPropagation()})).subscribe(()=>{history.replaceState({},"",`#${l.htmlFor}`),l.click()})}return B("content.tabs.link")&&s.pipe(Ce(1),re(t)).subscribe(([{active:c},{offset:l}])=>{let f=c.innerText.trim();if(c.hasAttribute("data-md-switching"))c.removeAttribute("data-md-switching");else{let u=e.offsetTop-l.y;for(let y of P("[data-tabs]"))for(let L of P(":scope > input",y)){let X=R(`label[for="${L.id}"]`);if(X!==c&&X.innerText.trim()===f){X.setAttribute("data-md-switching",""),L.click();break}}window.scrollTo({top:e.offsetTop-u});let d=__md_get("__tabs")||[];__md_set("__tabs",[...new Set([f,...d])])}}),s.pipe(W(p)).subscribe(()=>{for(let c of P("audio, video",e))c.pause()}),Ya(n).pipe(w(c=>s.next(c)),_(()=>s.complete()),m(c=>$({ref:e},c)))}).pipe(Ke(se))}function zn(e,{viewport$:t,target$:r,print$:o}){return O(...P(".annotate:not(.highlight)",e).map(n=>Pn(n,{target$:r,print$:o})),...P("pre:not(.mermaid) > code",e).map(n=>jn(n,{target$:r,print$:o})),...P("pre.mermaid",e).map(n=>Wn(n)),...P("table:not([class])",e).map(n=>Vn(n)),...P("details",e).map(n=>Fn(n,{target$:r,print$:o})),...P("[data-tabs]",e).map(n=>Nn(n,{viewport$:t,target$:r})),...P("[title]",e).filter(()=>B("content.tooltips")).map(n=>mt(n,{viewport$:t})))}function Ba(e,{alert$:t}){return t.pipe(v(r=>O(I(!0),I(!1).pipe(Ge(2e3))).pipe(m(o=>({message:r,active:o})))))}function qn(e,t){let r=R(".md-typeset",e);return C(()=>{let o=new g;return o.subscribe(({message:n,active:i})=>{e.classList.toggle("md-dialog--active",i),r.textContent=n}),Ba(e,t).pipe(w(n=>o.next(n)),_(()=>o.complete()),m(n=>$({ref:e},n)))})}var Ga=0;function Ja(e,t){document.body.append(e);let{width:r}=ce(e);e.style.setProperty("--md-tooltip-width",`${r}px`),e.remove();let o=cr(t),n=typeof o!="undefined"?Ne(o):I({x:0,y:0}),i=O(et(t),$t(t)).pipe(K());return z([i,n]).pipe(m(([a,s])=>{let{x:p,y:c}=Ve(t),l=ce(t),f=t.closest("table");return f&&t.parentElement&&(p+=f.offsetLeft+t.parentElement.offsetLeft,c+=f.offsetTop+t.parentElement.offsetTop),{active:a,offset:{x:p-s.x+l.width/2-r/2,y:c-s.y+l.height+8}}}))}function Qn(e){let t=e.title;if(!t.length)return S;let r=`__tooltip_${Ga++}`,o=Rt(r,"inline"),n=R(".md-typeset",o);return n.innerHTML=t,C(()=>{let i=new g;return i.subscribe({next({offset:a}){o.style.setProperty("--md-tooltip-x",`${a.x}px`),o.style.setProperty("--md-tooltip-y",`${a.y}px`)},complete(){o.style.removeProperty("--md-tooltip-x"),o.style.removeProperty("--md-tooltip-y")}}),O(i.pipe(b(({active:a})=>a)),i.pipe(_e(250),b(({active:a})=>!a))).subscribe({next({active:a}){a?(e.insertAdjacentElement("afterend",o),e.setAttribute("aria-describedby",r),e.removeAttribute("title")):(o.remove(),e.removeAttribute("aria-describedby"),e.setAttribute("title",t))},complete(){o.remove(),e.removeAttribute("aria-describedby"),e.setAttribute("title",t)}}),i.pipe(Me(16,me)).subscribe(({active:a})=>{o.classList.toggle("md-tooltip--active",a)}),i.pipe(pt(125,me),b(()=>!!e.offsetParent),m(()=>e.offsetParent.getBoundingClientRect()),m(({x:a})=>a)).subscribe({next(a){a?o.style.setProperty("--md-tooltip-0",`${-a}px`):o.style.removeProperty("--md-tooltip-0")},complete(){o.style.removeProperty("--md-tooltip-0")}}),Ja(o,e).pipe(w(a=>i.next(a)),_(()=>i.complete()),m(a=>$({ref:e},a)))}).pipe(Ke(se))}function Xa({viewport$:e}){if(!B("header.autohide"))return I(!1);let t=e.pipe(m(({offset:{y:n}})=>n),Be(2,1),m(([n,i])=>[nMath.abs(i-n.y)>100),m(([,[n]])=>n),K()),o=ze("search");return z([e,o]).pipe(m(([{offset:n},i])=>n.y>400&&!i),K(),v(n=>n?r:I(!1)),Q(!1))}function Kn(e,t){return C(()=>z([ge(e),Xa(t)])).pipe(m(([{height:r},o])=>({height:r,hidden:o})),K((r,o)=>r.height===o.height&&r.hidden===o.hidden),G(1))}function Yn(e,{header$:t,main$:r}){return C(()=>{let o=new g,n=o.pipe(Z(),ie(!0));o.pipe(ee("active"),He(t)).subscribe(([{active:a},{hidden:s}])=>{e.classList.toggle("md-header--shadow",a&&!s),e.hidden=s});let i=ue(P("[title]",e)).pipe(b(()=>B("content.tooltips")),ne(a=>Qn(a)));return r.subscribe(o),t.pipe(W(n),m(a=>$({ref:e},a)),Re(i.pipe(W(n))))})}function Za(e,{viewport$:t,header$:r}){return mr(e,{viewport$:t,header$:r}).pipe(m(({offset:{y:o}})=>{let{height:n}=ce(e);return{active:o>=n}}),ee("active"))}function Bn(e,t){return C(()=>{let r=new g;r.subscribe({next({active:n}){e.classList.toggle("md-header__title--active",n)},complete(){e.classList.remove("md-header__title--active")}});let o=fe(".md-content h1");return typeof o=="undefined"?S:Za(o,t).pipe(w(n=>r.next(n)),_(()=>r.complete()),m(n=>$({ref:e},n)))})}function Gn(e,{viewport$:t,header$:r}){let o=r.pipe(m(({height:i})=>i),K()),n=o.pipe(v(()=>ge(e).pipe(m(({height:i})=>({top:e.offsetTop,bottom:e.offsetTop+i})),ee("bottom"))));return z([o,n,t]).pipe(m(([i,{top:a,bottom:s},{offset:{y:p},size:{height:c}}])=>(c=Math.max(0,c-Math.max(0,a-p,i)-Math.max(0,c+p-s)),{offset:a-i,height:c,active:a-i<=p})),K((i,a)=>i.offset===a.offset&&i.height===a.height&&i.active===a.active))}function es(e){let t=__md_get("__palette")||{index:e.findIndex(o=>matchMedia(o.getAttribute("data-md-color-media")).matches)},r=Math.max(0,Math.min(t.index,e.length-1));return I(...e).pipe(ne(o=>h(o,"change").pipe(m(()=>o))),Q(e[r]),m(o=>({index:e.indexOf(o),color:{media:o.getAttribute("data-md-color-media"),scheme:o.getAttribute("data-md-color-scheme"),primary:o.getAttribute("data-md-color-primary"),accent:o.getAttribute("data-md-color-accent")}})),G(1))}function Jn(e){let t=P("input",e),r=x("meta",{name:"theme-color"});document.head.appendChild(r);let o=x("meta",{name:"color-scheme"});document.head.appendChild(o);let n=Pt("(prefers-color-scheme: light)");return C(()=>{let i=new g;return i.subscribe(a=>{if(document.body.setAttribute("data-md-color-switching",""),a.color.media==="(prefers-color-scheme)"){let s=matchMedia("(prefers-color-scheme: light)"),p=document.querySelector(s.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");a.color.scheme=p.getAttribute("data-md-color-scheme"),a.color.primary=p.getAttribute("data-md-color-primary"),a.color.accent=p.getAttribute("data-md-color-accent")}for(let[s,p]of Object.entries(a.color))document.body.setAttribute(`data-md-color-${s}`,p);for(let s=0;sa.key==="Enter"),re(i,(a,s)=>s)).subscribe(({index:a})=>{a=(a+1)%t.length,t[a].click(),t[a].focus()}),i.pipe(m(()=>{let a=Se("header"),s=window.getComputedStyle(a);return o.content=s.colorScheme,s.backgroundColor.match(/\d+/g).map(p=>(+p).toString(16).padStart(2,"0")).join("")})).subscribe(a=>r.content=`#${a}`),i.pipe(ve(se)).subscribe(()=>{document.body.removeAttribute("data-md-color-switching")}),es(t).pipe(W(n.pipe(Ce(1))),ct(),w(a=>i.next(a)),_(()=>i.complete()),m(a=>$({ref:e},a)))})}function Xn(e,{progress$:t}){return C(()=>{let r=new g;return r.subscribe(({value:o})=>{e.style.setProperty("--md-progress-value",`${o}`)}),t.pipe(w(o=>r.next({value:o})),_(()=>r.complete()),m(o=>({ref:e,value:o})))})}var Jr=Mt(Br());function ts(e){e.setAttribute("data-md-copying","");let t=e.closest("[data-copy]"),r=t?t.getAttribute("data-copy"):e.innerText;return e.removeAttribute("data-md-copying"),r.trimEnd()}function Zn({alert$:e}){Jr.default.isSupported()&&new j(t=>{new Jr.default("[data-clipboard-target], [data-clipboard-text]",{text:r=>r.getAttribute("data-clipboard-text")||ts(R(r.getAttribute("data-clipboard-target")))}).on("success",r=>t.next(r))}).pipe(w(t=>{t.trigger.focus()}),m(()=>Ee("clipboard.copied"))).subscribe(e)}function ei(e,t){return e.protocol=t.protocol,e.hostname=t.hostname,e}function rs(e,t){let r=new Map;for(let o of P("url",e)){let n=R("loc",o),i=[ei(new URL(n.textContent),t)];r.set(`${i[0]}`,i);for(let a of P("[rel=alternate]",o)){let s=a.getAttribute("href");s!=null&&i.push(ei(new URL(s),t))}}return r}function ur(e){return un(new URL("sitemap.xml",e)).pipe(m(t=>rs(t,new URL(e))),de(()=>I(new Map)))}function os(e,t){if(!(e.target instanceof Element))return S;let r=e.target.closest("a");if(r===null)return S;if(r.target||e.metaKey||e.ctrlKey)return S;let o=new URL(r.href);return o.search=o.hash="",t.has(`${o}`)?(e.preventDefault(),I(new URL(r.href))):S}function ti(e){let t=new Map;for(let r of P(":scope > *",e.head))t.set(r.outerHTML,r);return t}function ri(e){for(let t of P("[href], [src]",e))for(let r of["href","src"]){let o=t.getAttribute(r);if(o&&!/^(?:[a-z]+:)?\/\//i.test(o)){t[r]=t[r];break}}return I(e)}function ns(e){for(let o of["[data-md-component=announce]","[data-md-component=container]","[data-md-component=header-topic]","[data-md-component=outdated]","[data-md-component=logo]","[data-md-component=skip]",...B("navigation.tabs.sticky")?["[data-md-component=tabs]"]:[]]){let n=fe(o),i=fe(o,e);typeof n!="undefined"&&typeof i!="undefined"&&n.replaceWith(i)}let t=ti(document);for(let[o,n]of ti(e))t.has(o)?t.delete(o):document.head.appendChild(n);for(let o of t.values()){let n=o.getAttribute("name");n!=="theme-color"&&n!=="color-scheme"&&o.remove()}let r=Se("container");return We(P("script",r)).pipe(v(o=>{let n=e.createElement("script");if(o.src){for(let i of o.getAttributeNames())n.setAttribute(i,o.getAttribute(i));return o.replaceWith(n),new j(i=>{n.onload=()=>i.complete()})}else return n.textContent=o.textContent,o.replaceWith(n),S}),Z(),ie(document))}function oi({location$:e,viewport$:t,progress$:r}){let o=xe();if(location.protocol==="file:")return S;let n=ur(o.base);I(document).subscribe(ri);let i=h(document.body,"click").pipe(He(n),v(([p,c])=>os(p,c)),pe()),a=h(window,"popstate").pipe(m(ye),pe());i.pipe(re(t)).subscribe(([p,{offset:c}])=>{history.replaceState(c,""),history.pushState(null,"",p)}),O(i,a).subscribe(e);let s=e.pipe(ee("pathname"),v(p=>fn(p,{progress$:r}).pipe(de(()=>(lt(p,!0),S)))),v(ri),v(ns),pe());return O(s.pipe(re(e,(p,c)=>c)),s.pipe(v(()=>e),ee("pathname"),v(()=>e),ee("hash")),e.pipe(K((p,c)=>p.pathname===c.pathname&&p.hash===c.hash),v(()=>i),w(()=>history.back()))).subscribe(p=>{var c,l;history.state!==null||!p.hash?window.scrollTo(0,(l=(c=history.state)==null?void 0:c.y)!=null?l:0):(history.scrollRestoration="auto",pn(p.hash),history.scrollRestoration="manual")}),e.subscribe(()=>{history.scrollRestoration="manual"}),h(window,"beforeunload").subscribe(()=>{history.scrollRestoration="auto"}),t.pipe(ee("offset"),_e(100)).subscribe(({offset:p})=>{history.replaceState(p,"")}),s}var ni=Mt(qr());function ii(e){let t=e.separator.split("|").map(n=>n.replace(/(\(\?[!=<][^)]+\))/g,"").length===0?"\uFFFD":n).join("|"),r=new RegExp(t,"img"),o=(n,i,a)=>`${i}${a}`;return n=>{n=n.replace(/[\s*+\-:~^]+/g," ").trim();let i=new RegExp(`(^|${e.separator}|)(${n.replace(/[|\\{}()[\]^$+*?.-]/g,"\\$&").replace(r,"|")})`,"img");return a=>(0,ni.default)(a).replace(i,o).replace(/<\/mark>(\s+)]*>/img,"$1")}}function jt(e){return e.type===1}function dr(e){return e.type===3}function ai(e,t){let r=yn(e);return O(I(location.protocol!=="file:"),ze("search")).pipe(Ae(o=>o),v(()=>t)).subscribe(({config:o,docs:n})=>r.next({type:0,data:{config:o,docs:n,options:{suggest:B("search.suggest")}}})),r}function si(e){var l;let{selectedVersionSitemap:t,selectedVersionBaseURL:r,currentLocation:o,currentBaseURL:n}=e,i=(l=Xr(n))==null?void 0:l.pathname;if(i===void 0)return;let a=ss(o.pathname,i);if(a===void 0)return;let s=ps(t.keys());if(!t.has(s))return;let p=Xr(a,s);if(!p||!t.has(p.href))return;let c=Xr(a,r);if(c)return c.hash=o.hash,c.search=o.search,c}function Xr(e,t){try{return new URL(e,t)}catch(r){return}}function ss(e,t){if(e.startsWith(t))return e.slice(t.length)}function cs(e,t){let r=Math.min(e.length,t.length),o;for(o=0;oS)),o=r.pipe(m(n=>{let[,i]=t.base.match(/([^/]+)\/?$/);return n.find(({version:a,aliases:s})=>a===i||s.includes(i))||n[0]}));r.pipe(m(n=>new Map(n.map(i=>[`${new URL(`../${i.version}/`,t.base)}`,i]))),v(n=>h(document.body,"click").pipe(b(i=>!i.metaKey&&!i.ctrlKey),re(o),v(([i,a])=>{if(i.target instanceof Element){let s=i.target.closest("a");if(s&&!s.target&&n.has(s.href)){let p=s.href;return!i.target.closest(".md-version")&&n.get(p)===a?S:(i.preventDefault(),I(new URL(p)))}}return S}),v(i=>ur(i).pipe(m(a=>{var s;return(s=si({selectedVersionSitemap:a,selectedVersionBaseURL:i,currentLocation:ye(),currentBaseURL:t.base}))!=null?s:i})))))).subscribe(n=>lt(n,!0)),z([r,o]).subscribe(([n,i])=>{R(".md-header__topic").appendChild(Cn(n,i))}),e.pipe(v(()=>o)).subscribe(n=>{var a;let i=__md_get("__outdated",sessionStorage);if(i===null){i=!0;let s=((a=t.version)==null?void 0:a.default)||"latest";Array.isArray(s)||(s=[s]);e:for(let p of s)for(let c of n.aliases.concat(n.version))if(new RegExp(p,"i").test(c)){i=!1;break e}__md_set("__outdated",i,sessionStorage)}if(i)for(let s of ae("outdated"))s.hidden=!1})}function ls(e,{worker$:t}){let{searchParams:r}=ye();r.has("q")&&(Je("search",!0),e.value=r.get("q"),e.focus(),ze("search").pipe(Ae(i=>!i)).subscribe(()=>{let i=ye();i.searchParams.delete("q"),history.replaceState({},"",`${i}`)}));let o=et(e),n=O(t.pipe(Ae(jt)),h(e,"keyup"),o).pipe(m(()=>e.value),K());return z([n,o]).pipe(m(([i,a])=>({value:i,focus:a})),G(1))}function pi(e,{worker$:t}){let r=new g,o=r.pipe(Z(),ie(!0));z([t.pipe(Ae(jt)),r],(i,a)=>a).pipe(ee("value")).subscribe(({value:i})=>t.next({type:2,data:i})),r.pipe(ee("focus")).subscribe(({focus:i})=>{i&&Je("search",i)}),h(e.form,"reset").pipe(W(o)).subscribe(()=>e.focus());let n=R("header [for=__search]");return h(n,"click").subscribe(()=>e.focus()),ls(e,{worker$:t}).pipe(w(i=>r.next(i)),_(()=>r.complete()),m(i=>$({ref:e},i)),G(1))}function li(e,{worker$:t,query$:r}){let o=new g,n=on(e.parentElement).pipe(b(Boolean)),i=e.parentElement,a=R(":scope > :first-child",e),s=R(":scope > :last-child",e);ze("search").subscribe(l=>s.setAttribute("role",l?"list":"presentation")),o.pipe(re(r),Wr(t.pipe(Ae(jt)))).subscribe(([{items:l},{value:f}])=>{switch(l.length){case 0:a.textContent=f.length?Ee("search.result.none"):Ee("search.result.placeholder");break;case 1:a.textContent=Ee("search.result.one");break;default:let u=sr(l.length);a.textContent=Ee("search.result.other",u)}});let p=o.pipe(w(()=>s.innerHTML=""),v(({items:l})=>O(I(...l.slice(0,10)),I(...l.slice(10)).pipe(Be(4),Vr(n),v(([f])=>f)))),m(Mn),pe());return p.subscribe(l=>s.appendChild(l)),p.pipe(ne(l=>{let f=fe("details",l);return typeof f=="undefined"?S:h(f,"toggle").pipe(W(o),m(()=>f))})).subscribe(l=>{l.open===!1&&l.offsetTop<=i.scrollTop&&i.scrollTo({top:l.offsetTop})}),t.pipe(b(dr),m(({data:l})=>l)).pipe(w(l=>o.next(l)),_(()=>o.complete()),m(l=>$({ref:e},l)))}function ms(e,{query$:t}){return t.pipe(m(({value:r})=>{let o=ye();return o.hash="",r=r.replace(/\s+/g,"+").replace(/&/g,"%26").replace(/=/g,"%3D"),o.search=`q=${r}`,{url:o}}))}function mi(e,t){let r=new g,o=r.pipe(Z(),ie(!0));return r.subscribe(({url:n})=>{e.setAttribute("data-clipboard-text",e.href),e.href=`${n}`}),h(e,"click").pipe(W(o)).subscribe(n=>n.preventDefault()),ms(e,t).pipe(w(n=>r.next(n)),_(()=>r.complete()),m(n=>$({ref:e},n)))}function fi(e,{worker$:t,keyboard$:r}){let o=new g,n=Se("search-query"),i=O(h(n,"keydown"),h(n,"focus")).pipe(ve(se),m(()=>n.value),K());return o.pipe(He(i),m(([{suggest:s},p])=>{let c=p.split(/([\s-]+)/);if(s!=null&&s.length&&c[c.length-1]){let l=s[s.length-1];l.startsWith(c[c.length-1])&&(c[c.length-1]=l)}else c.length=0;return c})).subscribe(s=>e.innerHTML=s.join("").replace(/\s/g," ")),r.pipe(b(({mode:s})=>s==="search")).subscribe(s=>{switch(s.type){case"ArrowRight":e.innerText.length&&n.selectionStart===n.value.length&&(n.value=e.innerText);break}}),t.pipe(b(dr),m(({data:s})=>s)).pipe(w(s=>o.next(s)),_(()=>o.complete()),m(()=>({ref:e})))}function ui(e,{index$:t,keyboard$:r}){let o=xe();try{let n=ai(o.search,t),i=Se("search-query",e),a=Se("search-result",e);h(e,"click").pipe(b(({target:p})=>p instanceof Element&&!!p.closest("a"))).subscribe(()=>Je("search",!1)),r.pipe(b(({mode:p})=>p==="search")).subscribe(p=>{let c=Ie();switch(p.type){case"Enter":if(c===i){let l=new Map;for(let f of P(":first-child [href]",a)){let u=f.firstElementChild;l.set(f,parseFloat(u.getAttribute("data-md-score")))}if(l.size){let[[f]]=[...l].sort(([,u],[,d])=>d-u);f.click()}p.claim()}break;case"Escape":case"Tab":Je("search",!1),i.blur();break;case"ArrowUp":case"ArrowDown":if(typeof c=="undefined")i.focus();else{let l=[i,...P(":not(details) > [href], summary, details[open] [href]",a)],f=Math.max(0,(Math.max(0,l.indexOf(c))+l.length+(p.type==="ArrowUp"?-1:1))%l.length);l[f].focus()}p.claim();break;default:i!==Ie()&&i.focus()}}),r.pipe(b(({mode:p})=>p==="global")).subscribe(p=>{switch(p.type){case"f":case"s":case"/":i.focus(),i.select(),p.claim();break}});let s=pi(i,{worker$:n});return O(s,li(a,{worker$:n,query$:s})).pipe(Re(...ae("search-share",e).map(p=>mi(p,{query$:s})),...ae("search-suggest",e).map(p=>fi(p,{worker$:n,keyboard$:r}))))}catch(n){return e.hidden=!0,Ye}}function di(e,{index$:t,location$:r}){return z([t,r.pipe(Q(ye()),b(o=>!!o.searchParams.get("h")))]).pipe(m(([o,n])=>ii(o.config)(n.searchParams.get("h"))),m(o=>{var a;let n=new Map,i=document.createNodeIterator(e,NodeFilter.SHOW_TEXT);for(let s=i.nextNode();s;s=i.nextNode())if((a=s.parentElement)!=null&&a.offsetHeight){let p=s.textContent,c=o(p);c.length>p.length&&n.set(s,c)}for(let[s,p]of n){let{childNodes:c}=x("span",null,p);s.replaceWith(...Array.from(c))}return{ref:e,nodes:n}}))}function fs(e,{viewport$:t,main$:r}){let o=e.closest(".md-grid"),n=o.offsetTop-o.parentElement.offsetTop;return z([r,t]).pipe(m(([{offset:i,height:a},{offset:{y:s}}])=>(a=a+Math.min(n,Math.max(0,s-i))-n,{height:a,locked:s>=i+n})),K((i,a)=>i.height===a.height&&i.locked===a.locked))}function Zr(e,o){var n=o,{header$:t}=n,r=so(n,["header$"]);let i=R(".md-sidebar__scrollwrap",e),{y:a}=Ve(i);return C(()=>{let s=new g,p=s.pipe(Z(),ie(!0)),c=s.pipe(Me(0,me));return c.pipe(re(t)).subscribe({next([{height:l},{height:f}]){i.style.height=`${l-2*a}px`,e.style.top=`${f}px`},complete(){i.style.height="",e.style.top=""}}),c.pipe(Ae()).subscribe(()=>{for(let l of P(".md-nav__link--active[href]",e)){if(!l.clientHeight)continue;let f=l.closest(".md-sidebar__scrollwrap");if(typeof f!="undefined"){let u=l.offsetTop-f.offsetTop,{height:d}=ce(f);f.scrollTo({top:u-d/2})}}}),ue(P("label[tabindex]",e)).pipe(ne(l=>h(l,"click").pipe(ve(se),m(()=>l),W(p)))).subscribe(l=>{let f=R(`[id="${l.htmlFor}"]`);R(`[aria-labelledby="${l.id}"]`).setAttribute("aria-expanded",`${f.checked}`)}),fs(e,r).pipe(w(l=>s.next(l)),_(()=>s.complete()),m(l=>$({ref:e},l)))})}function hi(e,t){if(typeof t!="undefined"){let r=`https://api.github.com/repos/${e}/${t}`;return st(je(`${r}/releases/latest`).pipe(de(()=>S),m(o=>({version:o.tag_name})),De({})),je(r).pipe(de(()=>S),m(o=>({stars:o.stargazers_count,forks:o.forks_count})),De({}))).pipe(m(([o,n])=>$($({},o),n)))}else{let r=`https://api.github.com/users/${e}`;return je(r).pipe(m(o=>({repositories:o.public_repos})),De({}))}}function bi(e,t){let r=`https://${e}/api/v4/projects/${encodeURIComponent(t)}`;return st(je(`${r}/releases/permalink/latest`).pipe(de(()=>S),m(({tag_name:o})=>({version:o})),De({})),je(r).pipe(de(()=>S),m(({star_count:o,forks_count:n})=>({stars:o,forks:n})),De({}))).pipe(m(([o,n])=>$($({},o),n)))}function vi(e){let t=e.match(/^.+github\.com\/([^/]+)\/?([^/]+)?/i);if(t){let[,r,o]=t;return hi(r,o)}if(t=e.match(/^.+?([^/]*gitlab[^/]+)\/(.+?)\/?$/i),t){let[,r,o]=t;return bi(r,o)}return S}var us;function ds(e){return us||(us=C(()=>{let t=__md_get("__source",sessionStorage);if(t)return I(t);if(ae("consent").length){let o=__md_get("__consent");if(!(o&&o.github))return S}return vi(e.href).pipe(w(o=>__md_set("__source",o,sessionStorage)))}).pipe(de(()=>S),b(t=>Object.keys(t).length>0),m(t=>({facts:t})),G(1)))}function gi(e){let t=R(":scope > :last-child",e);return C(()=>{let r=new g;return r.subscribe(({facts:o})=>{t.appendChild(_n(o)),t.classList.add("md-source__repository--active")}),ds(e).pipe(w(o=>r.next(o)),_(()=>r.complete()),m(o=>$({ref:e},o)))})}function hs(e,{viewport$:t,header$:r}){return ge(document.body).pipe(v(()=>mr(e,{header$:r,viewport$:t})),m(({offset:{y:o}})=>({hidden:o>=10})),ee("hidden"))}function yi(e,t){return C(()=>{let r=new g;return r.subscribe({next({hidden:o}){e.hidden=o},complete(){e.hidden=!1}}),(B("navigation.tabs.sticky")?I({hidden:!1}):hs(e,t)).pipe(w(o=>r.next(o)),_(()=>r.complete()),m(o=>$({ref:e},o)))})}function bs(e,{viewport$:t,header$:r}){let o=new Map,n=P(".md-nav__link",e);for(let s of n){let p=decodeURIComponent(s.hash.substring(1)),c=fe(`[id="${p}"]`);typeof c!="undefined"&&o.set(s,c)}let i=r.pipe(ee("height"),m(({height:s})=>{let p=Se("main"),c=R(":scope > :first-child",p);return s+.8*(c.offsetTop-p.offsetTop)}),pe());return ge(document.body).pipe(ee("height"),v(s=>C(()=>{let p=[];return I([...o].reduce((c,[l,f])=>{for(;p.length&&o.get(p[p.length-1]).tagName>=f.tagName;)p.pop();let u=f.offsetTop;for(;!u&&f.parentElement;)f=f.parentElement,u=f.offsetTop;let d=f.offsetParent;for(;d;d=d.offsetParent)u+=d.offsetTop;return c.set([...p=[...p,l]].reverse(),u)},new Map))}).pipe(m(p=>new Map([...p].sort(([,c],[,l])=>c-l))),He(i),v(([p,c])=>t.pipe(Fr(([l,f],{offset:{y:u},size:d})=>{let y=u+d.height>=Math.floor(s.height);for(;f.length;){let[,L]=f[0];if(L-c=u&&!y)f=[l.pop(),...f];else break}return[l,f]},[[],[...p]]),K((l,f)=>l[0]===f[0]&&l[1]===f[1])))))).pipe(m(([s,p])=>({prev:s.map(([c])=>c),next:p.map(([c])=>c)})),Q({prev:[],next:[]}),Be(2,1),m(([s,p])=>s.prev.length{let i=new g,a=i.pipe(Z(),ie(!0));if(i.subscribe(({prev:s,next:p})=>{for(let[c]of p)c.classList.remove("md-nav__link--passed"),c.classList.remove("md-nav__link--active");for(let[c,[l]]of s.entries())l.classList.add("md-nav__link--passed"),l.classList.toggle("md-nav__link--active",c===s.length-1)}),B("toc.follow")){let s=O(t.pipe(_e(1),m(()=>{})),t.pipe(_e(250),m(()=>"smooth")));i.pipe(b(({prev:p})=>p.length>0),He(o.pipe(ve(se))),re(s)).subscribe(([[{prev:p}],c])=>{let[l]=p[p.length-1];if(l.offsetHeight){let f=cr(l);if(typeof f!="undefined"){let u=l.offsetTop-f.offsetTop,{height:d}=ce(f);f.scrollTo({top:u-d/2,behavior:c})}}})}return B("navigation.tracking")&&t.pipe(W(a),ee("offset"),_e(250),Ce(1),W(n.pipe(Ce(1))),ct({delay:250}),re(i)).subscribe(([,{prev:s}])=>{let p=ye(),c=s[s.length-1];if(c&&c.length){let[l]=c,{hash:f}=new URL(l.href);p.hash!==f&&(p.hash=f,history.replaceState({},"",`${p}`))}else p.hash="",history.replaceState({},"",`${p}`)}),bs(e,{viewport$:t,header$:r}).pipe(w(s=>i.next(s)),_(()=>i.complete()),m(s=>$({ref:e},s)))})}function vs(e,{viewport$:t,main$:r,target$:o}){let n=t.pipe(m(({offset:{y:a}})=>a),Be(2,1),m(([a,s])=>a>s&&s>0),K()),i=r.pipe(m(({active:a})=>a));return z([i,n]).pipe(m(([a,s])=>!(a&&s)),K(),W(o.pipe(Ce(1))),ie(!0),ct({delay:250}),m(a=>({hidden:a})))}function Ei(e,{viewport$:t,header$:r,main$:o,target$:n}){let i=new g,a=i.pipe(Z(),ie(!0));return i.subscribe({next({hidden:s}){e.hidden=s,s?(e.setAttribute("tabindex","-1"),e.blur()):e.removeAttribute("tabindex")},complete(){e.style.top="",e.hidden=!0,e.removeAttribute("tabindex")}}),r.pipe(W(a),ee("height")).subscribe(({height:s})=>{e.style.top=`${s+16}px`}),h(e,"click").subscribe(s=>{s.preventDefault(),window.scrollTo({top:0})}),vs(e,{viewport$:t,main$:o,target$:n}).pipe(w(s=>i.next(s)),_(()=>i.complete()),m(s=>$({ref:e},s)))}function wi({document$:e,viewport$:t}){e.pipe(v(()=>P(".md-ellipsis")),ne(r=>tt(r).pipe(W(e.pipe(Ce(1))),b(o=>o),m(()=>r),Te(1))),b(r=>r.offsetWidth{let o=r.innerText,n=r.closest("a")||r;return n.title=o,B("content.tooltips")?mt(n,{viewport$:t}).pipe(W(e.pipe(Ce(1))),_(()=>n.removeAttribute("title"))):S})).subscribe(),B("content.tooltips")&&e.pipe(v(()=>P(".md-status")),ne(r=>mt(r,{viewport$:t}))).subscribe()}function Ti({document$:e,tablet$:t}){e.pipe(v(()=>P(".md-toggle--indeterminate")),w(r=>{r.indeterminate=!0,r.checked=!1}),ne(r=>h(r,"change").pipe(Dr(()=>r.classList.contains("md-toggle--indeterminate")),m(()=>r))),re(t)).subscribe(([r,o])=>{r.classList.remove("md-toggle--indeterminate"),o&&(r.checked=!1)})}function gs(){return/(iPad|iPhone|iPod)/.test(navigator.userAgent)}function Si({document$:e}){e.pipe(v(()=>P("[data-md-scrollfix]")),w(t=>t.removeAttribute("data-md-scrollfix")),b(gs),ne(t=>h(t,"touchstart").pipe(m(()=>t)))).subscribe(t=>{let r=t.scrollTop;r===0?t.scrollTop=1:r+t.offsetHeight===t.scrollHeight&&(t.scrollTop=r-1)})}function Oi({viewport$:e,tablet$:t}){z([ze("search"),t]).pipe(m(([r,o])=>r&&!o),v(r=>I(r).pipe(Ge(r?400:100))),re(e)).subscribe(([r,{offset:{y:o}}])=>{if(r)document.body.setAttribute("data-md-scrolllock",""),document.body.style.top=`-${o}px`;else{let n=-1*parseInt(document.body.style.top,10);document.body.removeAttribute("data-md-scrolllock"),document.body.style.top="",n&&window.scrollTo(0,n)}})}Object.entries||(Object.entries=function(e){let t=[];for(let r of Object.keys(e))t.push([r,e[r]]);return t});Object.values||(Object.values=function(e){let t=[];for(let r of Object.keys(e))t.push(e[r]);return t});typeof Element!="undefined"&&(Element.prototype.scrollTo||(Element.prototype.scrollTo=function(e,t){typeof e=="object"?(this.scrollLeft=e.left,this.scrollTop=e.top):(this.scrollLeft=e,this.scrollTop=t)}),Element.prototype.replaceWith||(Element.prototype.replaceWith=function(...e){let t=this.parentNode;if(t){e.length===0&&t.removeChild(this);for(let r=e.length-1;r>=0;r--){let o=e[r];typeof o=="string"?o=document.createTextNode(o):o.parentNode&&o.parentNode.removeChild(o),r?t.insertBefore(this.previousSibling,o):t.replaceChild(o,this)}}}));function ys(){return location.protocol==="file:"?Tt(`${new URL("search/search_index.js",eo.base)}`).pipe(m(()=>__index),G(1)):je(new URL("search/search_index.json",eo.base))}document.documentElement.classList.remove("no-js");document.documentElement.classList.add("js");var ot=Go(),Ut=sn(),Lt=ln(Ut),to=an(),Oe=gn(),hr=Pt("(min-width: 960px)"),Mi=Pt("(min-width: 1220px)"),_i=mn(),eo=xe(),Ai=document.forms.namedItem("search")?ys():Ye,ro=new g;Zn({alert$:ro});var oo=new g;B("navigation.instant")&&oi({location$:Ut,viewport$:Oe,progress$:oo}).subscribe(ot);var Li;((Li=eo.version)==null?void 0:Li.provider)==="mike"&&ci({document$:ot});O(Ut,Lt).pipe(Ge(125)).subscribe(()=>{Je("drawer",!1),Je("search",!1)});to.pipe(b(({mode:e})=>e==="global")).subscribe(e=>{switch(e.type){case"p":case",":let t=fe("link[rel=prev]");typeof t!="undefined"&<(t);break;case"n":case".":let r=fe("link[rel=next]");typeof r!="undefined"&<(r);break;case"Enter":let o=Ie();o instanceof HTMLLabelElement&&o.click()}});wi({viewport$:Oe,document$:ot});Ti({document$:ot,tablet$:hr});Si({document$:ot});Oi({viewport$:Oe,tablet$:hr});var rt=Kn(Se("header"),{viewport$:Oe}),Ft=ot.pipe(m(()=>Se("main")),v(e=>Gn(e,{viewport$:Oe,header$:rt})),G(1)),xs=O(...ae("consent").map(e=>En(e,{target$:Lt})),...ae("dialog").map(e=>qn(e,{alert$:ro})),...ae("palette").map(e=>Jn(e)),...ae("progress").map(e=>Xn(e,{progress$:oo})),...ae("search").map(e=>ui(e,{index$:Ai,keyboard$:to})),...ae("source").map(e=>gi(e))),Es=C(()=>O(...ae("announce").map(e=>xn(e)),...ae("content").map(e=>zn(e,{viewport$:Oe,target$:Lt,print$:_i})),...ae("content").map(e=>B("search.highlight")?di(e,{index$:Ai,location$:Ut}):S),...ae("header").map(e=>Yn(e,{viewport$:Oe,header$:rt,main$:Ft})),...ae("header-title").map(e=>Bn(e,{viewport$:Oe,header$:rt})),...ae("sidebar").map(e=>e.getAttribute("data-md-type")==="navigation"?Nr(Mi,()=>Zr(e,{viewport$:Oe,header$:rt,main$:Ft})):Nr(hr,()=>Zr(e,{viewport$:Oe,header$:rt,main$:Ft}))),...ae("tabs").map(e=>yi(e,{viewport$:Oe,header$:rt})),...ae("toc").map(e=>xi(e,{viewport$:Oe,header$:rt,main$:Ft,target$:Lt})),...ae("top").map(e=>Ei(e,{viewport$:Oe,header$:rt,main$:Ft,target$:Lt})))),Ci=ot.pipe(v(()=>Es),Re(xs),G(1));Ci.subscribe();window.document$=ot;window.location$=Ut;window.target$=Lt;window.keyboard$=to;window.viewport$=Oe;window.tablet$=hr;window.screen$=Mi;window.print$=_i;window.alert$=ro;window.progress$=oo;window.component$=Ci;})(); +//# sourceMappingURL=bundle.60a45f97.min.js.map + diff --git a/611/assets/javascripts/bundle.60a45f97.min.js.map b/611/assets/javascripts/bundle.60a45f97.min.js.map new file mode 100644 index 000000000..7edbc6f43 --- /dev/null +++ b/611/assets/javascripts/bundle.60a45f97.min.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["node_modules/focus-visible/dist/focus-visible.js", "node_modules/escape-html/index.js", "node_modules/clipboard/dist/clipboard.js", "src/templates/assets/javascripts/bundle.ts", "node_modules/tslib/tslib.es6.mjs", "node_modules/rxjs/src/internal/util/isFunction.ts", "node_modules/rxjs/src/internal/util/createErrorClass.ts", "node_modules/rxjs/src/internal/util/UnsubscriptionError.ts", "node_modules/rxjs/src/internal/util/arrRemove.ts", "node_modules/rxjs/src/internal/Subscription.ts", "node_modules/rxjs/src/internal/config.ts", "node_modules/rxjs/src/internal/scheduler/timeoutProvider.ts", "node_modules/rxjs/src/internal/util/reportUnhandledError.ts", "node_modules/rxjs/src/internal/util/noop.ts", "node_modules/rxjs/src/internal/NotificationFactories.ts", "node_modules/rxjs/src/internal/util/errorContext.ts", "node_modules/rxjs/src/internal/Subscriber.ts", "node_modules/rxjs/src/internal/symbol/observable.ts", "node_modules/rxjs/src/internal/util/identity.ts", "node_modules/rxjs/src/internal/util/pipe.ts", "node_modules/rxjs/src/internal/Observable.ts", "node_modules/rxjs/src/internal/util/lift.ts", "node_modules/rxjs/src/internal/operators/OperatorSubscriber.ts", "node_modules/rxjs/src/internal/scheduler/animationFrameProvider.ts", "node_modules/rxjs/src/internal/util/ObjectUnsubscribedError.ts", "node_modules/rxjs/src/internal/Subject.ts", "node_modules/rxjs/src/internal/BehaviorSubject.ts", "node_modules/rxjs/src/internal/scheduler/dateTimestampProvider.ts", "node_modules/rxjs/src/internal/ReplaySubject.ts", "node_modules/rxjs/src/internal/scheduler/Action.ts", "node_modules/rxjs/src/internal/scheduler/intervalProvider.ts", "node_modules/rxjs/src/internal/scheduler/AsyncAction.ts", "node_modules/rxjs/src/internal/Scheduler.ts", "node_modules/rxjs/src/internal/scheduler/AsyncScheduler.ts", "node_modules/rxjs/src/internal/scheduler/async.ts", "node_modules/rxjs/src/internal/scheduler/QueueAction.ts", "node_modules/rxjs/src/internal/scheduler/QueueScheduler.ts", "node_modules/rxjs/src/internal/scheduler/queue.ts", "node_modules/rxjs/src/internal/scheduler/AnimationFrameAction.ts", "node_modules/rxjs/src/internal/scheduler/AnimationFrameScheduler.ts", "node_modules/rxjs/src/internal/scheduler/animationFrame.ts", "node_modules/rxjs/src/internal/observable/empty.ts", "node_modules/rxjs/src/internal/util/isScheduler.ts", "node_modules/rxjs/src/internal/util/args.ts", "node_modules/rxjs/src/internal/util/isArrayLike.ts", "node_modules/rxjs/src/internal/util/isPromise.ts", "node_modules/rxjs/src/internal/util/isInteropObservable.ts", "node_modules/rxjs/src/internal/util/isAsyncIterable.ts", "node_modules/rxjs/src/internal/util/throwUnobservableError.ts", "node_modules/rxjs/src/internal/symbol/iterator.ts", "node_modules/rxjs/src/internal/util/isIterable.ts", "node_modules/rxjs/src/internal/util/isReadableStreamLike.ts", "node_modules/rxjs/src/internal/observable/innerFrom.ts", "node_modules/rxjs/src/internal/util/executeSchedule.ts", "node_modules/rxjs/src/internal/operators/observeOn.ts", "node_modules/rxjs/src/internal/operators/subscribeOn.ts", "node_modules/rxjs/src/internal/scheduled/scheduleObservable.ts", "node_modules/rxjs/src/internal/scheduled/schedulePromise.ts", "node_modules/rxjs/src/internal/scheduled/scheduleArray.ts", "node_modules/rxjs/src/internal/scheduled/scheduleIterable.ts", "node_modules/rxjs/src/internal/scheduled/scheduleAsyncIterable.ts", "node_modules/rxjs/src/internal/scheduled/scheduleReadableStreamLike.ts", "node_modules/rxjs/src/internal/scheduled/scheduled.ts", "node_modules/rxjs/src/internal/observable/from.ts", "node_modules/rxjs/src/internal/observable/of.ts", "node_modules/rxjs/src/internal/observable/throwError.ts", "node_modules/rxjs/src/internal/util/EmptyError.ts", "node_modules/rxjs/src/internal/util/isDate.ts", "node_modules/rxjs/src/internal/operators/map.ts", "node_modules/rxjs/src/internal/util/mapOneOrManyArgs.ts", "node_modules/rxjs/src/internal/util/argsArgArrayOrObject.ts", "node_modules/rxjs/src/internal/util/createObject.ts", "node_modules/rxjs/src/internal/observable/combineLatest.ts", "node_modules/rxjs/src/internal/operators/mergeInternals.ts", "node_modules/rxjs/src/internal/operators/mergeMap.ts", "node_modules/rxjs/src/internal/operators/mergeAll.ts", "node_modules/rxjs/src/internal/operators/concatAll.ts", "node_modules/rxjs/src/internal/observable/concat.ts", "node_modules/rxjs/src/internal/observable/defer.ts", "node_modules/rxjs/src/internal/observable/fromEvent.ts", "node_modules/rxjs/src/internal/observable/fromEventPattern.ts", "node_modules/rxjs/src/internal/observable/timer.ts", "node_modules/rxjs/src/internal/observable/merge.ts", "node_modules/rxjs/src/internal/observable/never.ts", "node_modules/rxjs/src/internal/util/argsOrArgArray.ts", "node_modules/rxjs/src/internal/operators/filter.ts", "node_modules/rxjs/src/internal/observable/zip.ts", "node_modules/rxjs/src/internal/operators/audit.ts", "node_modules/rxjs/src/internal/operators/auditTime.ts", "node_modules/rxjs/src/internal/operators/bufferCount.ts", "node_modules/rxjs/src/internal/operators/catchError.ts", "node_modules/rxjs/src/internal/operators/scanInternals.ts", "node_modules/rxjs/src/internal/operators/combineLatest.ts", "node_modules/rxjs/src/internal/operators/combineLatestWith.ts", "node_modules/rxjs/src/internal/operators/debounce.ts", "node_modules/rxjs/src/internal/operators/debounceTime.ts", "node_modules/rxjs/src/internal/operators/defaultIfEmpty.ts", "node_modules/rxjs/src/internal/operators/take.ts", "node_modules/rxjs/src/internal/operators/ignoreElements.ts", "node_modules/rxjs/src/internal/operators/mapTo.ts", "node_modules/rxjs/src/internal/operators/delayWhen.ts", "node_modules/rxjs/src/internal/operators/delay.ts", "node_modules/rxjs/src/internal/operators/distinctUntilChanged.ts", "node_modules/rxjs/src/internal/operators/distinctUntilKeyChanged.ts", "node_modules/rxjs/src/internal/operators/throwIfEmpty.ts", "node_modules/rxjs/src/internal/operators/endWith.ts", "node_modules/rxjs/src/internal/operators/finalize.ts", "node_modules/rxjs/src/internal/operators/first.ts", "node_modules/rxjs/src/internal/operators/takeLast.ts", "node_modules/rxjs/src/internal/operators/merge.ts", "node_modules/rxjs/src/internal/operators/mergeWith.ts", "node_modules/rxjs/src/internal/operators/repeat.ts", "node_modules/rxjs/src/internal/operators/scan.ts", "node_modules/rxjs/src/internal/operators/share.ts", "node_modules/rxjs/src/internal/operators/shareReplay.ts", "node_modules/rxjs/src/internal/operators/skip.ts", "node_modules/rxjs/src/internal/operators/skipUntil.ts", "node_modules/rxjs/src/internal/operators/startWith.ts", "node_modules/rxjs/src/internal/operators/switchMap.ts", "node_modules/rxjs/src/internal/operators/takeUntil.ts", "node_modules/rxjs/src/internal/operators/takeWhile.ts", "node_modules/rxjs/src/internal/operators/tap.ts", "node_modules/rxjs/src/internal/operators/throttle.ts", "node_modules/rxjs/src/internal/operators/throttleTime.ts", "node_modules/rxjs/src/internal/operators/withLatestFrom.ts", "node_modules/rxjs/src/internal/operators/zip.ts", "node_modules/rxjs/src/internal/operators/zipWith.ts", "src/templates/assets/javascripts/browser/document/index.ts", "src/templates/assets/javascripts/browser/element/_/index.ts", "src/templates/assets/javascripts/browser/element/focus/index.ts", "src/templates/assets/javascripts/browser/element/hover/index.ts", "src/templates/assets/javascripts/utilities/h/index.ts", "src/templates/assets/javascripts/utilities/round/index.ts", "src/templates/assets/javascripts/browser/script/index.ts", "src/templates/assets/javascripts/browser/element/size/_/index.ts", "src/templates/assets/javascripts/browser/element/size/content/index.ts", "src/templates/assets/javascripts/browser/element/offset/_/index.ts", "src/templates/assets/javascripts/browser/element/offset/content/index.ts", "src/templates/assets/javascripts/browser/element/visibility/index.ts", "src/templates/assets/javascripts/browser/toggle/index.ts", "src/templates/assets/javascripts/browser/keyboard/index.ts", "src/templates/assets/javascripts/browser/location/_/index.ts", "src/templates/assets/javascripts/browser/location/hash/index.ts", "src/templates/assets/javascripts/browser/media/index.ts", "src/templates/assets/javascripts/browser/request/index.ts", "src/templates/assets/javascripts/browser/viewport/offset/index.ts", "src/templates/assets/javascripts/browser/viewport/size/index.ts", "src/templates/assets/javascripts/browser/viewport/_/index.ts", "src/templates/assets/javascripts/browser/viewport/at/index.ts", "src/templates/assets/javascripts/browser/worker/index.ts", "src/templates/assets/javascripts/_/index.ts", "src/templates/assets/javascripts/components/_/index.ts", "src/templates/assets/javascripts/components/announce/index.ts", "src/templates/assets/javascripts/components/consent/index.ts", "src/templates/assets/javascripts/templates/tooltip/index.tsx", "src/templates/assets/javascripts/templates/annotation/index.tsx", "src/templates/assets/javascripts/templates/clipboard/index.tsx", "src/templates/assets/javascripts/templates/search/index.tsx", "src/templates/assets/javascripts/templates/source/index.tsx", "src/templates/assets/javascripts/templates/tabbed/index.tsx", "src/templates/assets/javascripts/templates/table/index.tsx", "src/templates/assets/javascripts/templates/version/index.tsx", "src/templates/assets/javascripts/components/tooltip2/index.ts", "src/templates/assets/javascripts/components/content/annotation/_/index.ts", "src/templates/assets/javascripts/components/content/annotation/list/index.ts", "src/templates/assets/javascripts/components/content/annotation/block/index.ts", "src/templates/assets/javascripts/components/content/code/_/index.ts", "src/templates/assets/javascripts/components/content/details/index.ts", "src/templates/assets/javascripts/components/content/mermaid/index.css", "src/templates/assets/javascripts/components/content/mermaid/index.ts", "src/templates/assets/javascripts/components/content/table/index.ts", "src/templates/assets/javascripts/components/content/tabs/index.ts", "src/templates/assets/javascripts/components/content/_/index.ts", "src/templates/assets/javascripts/components/dialog/index.ts", "src/templates/assets/javascripts/components/tooltip/index.ts", "src/templates/assets/javascripts/components/header/_/index.ts", "src/templates/assets/javascripts/components/header/title/index.ts", "src/templates/assets/javascripts/components/main/index.ts", "src/templates/assets/javascripts/components/palette/index.ts", "src/templates/assets/javascripts/components/progress/index.ts", "src/templates/assets/javascripts/integrations/clipboard/index.ts", "src/templates/assets/javascripts/integrations/sitemap/index.ts", "src/templates/assets/javascripts/integrations/instant/index.ts", "src/templates/assets/javascripts/integrations/search/highlighter/index.ts", "src/templates/assets/javascripts/integrations/search/worker/message/index.ts", "src/templates/assets/javascripts/integrations/search/worker/_/index.ts", "src/templates/assets/javascripts/integrations/version/findurl/index.ts", "src/templates/assets/javascripts/integrations/version/index.ts", "src/templates/assets/javascripts/components/search/query/index.ts", "src/templates/assets/javascripts/components/search/result/index.ts", "src/templates/assets/javascripts/components/search/share/index.ts", "src/templates/assets/javascripts/components/search/suggest/index.ts", "src/templates/assets/javascripts/components/search/_/index.ts", "src/templates/assets/javascripts/components/search/highlight/index.ts", "src/templates/assets/javascripts/components/sidebar/index.ts", "src/templates/assets/javascripts/components/source/facts/github/index.ts", "src/templates/assets/javascripts/components/source/facts/gitlab/index.ts", "src/templates/assets/javascripts/components/source/facts/_/index.ts", "src/templates/assets/javascripts/components/source/_/index.ts", "src/templates/assets/javascripts/components/tabs/index.ts", "src/templates/assets/javascripts/components/toc/index.ts", "src/templates/assets/javascripts/components/top/index.ts", "src/templates/assets/javascripts/patches/ellipsis/index.ts", "src/templates/assets/javascripts/patches/indeterminate/index.ts", "src/templates/assets/javascripts/patches/scrollfix/index.ts", "src/templates/assets/javascripts/patches/scrolllock/index.ts", "src/templates/assets/javascripts/polyfills/index.ts"], + "sourcesContent": ["(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n (factory());\n}(this, (function () { 'use strict';\n\n /**\n * Applies the :focus-visible polyfill at the given scope.\n * A scope in this case is either the top-level Document or a Shadow Root.\n *\n * @param {(Document|ShadowRoot)} scope\n * @see https://github.com/WICG/focus-visible\n */\n function applyFocusVisiblePolyfill(scope) {\n var hadKeyboardEvent = true;\n var hadFocusVisibleRecently = false;\n var hadFocusVisibleRecentlyTimeout = null;\n\n var inputTypesAllowlist = {\n text: true,\n search: true,\n url: true,\n tel: true,\n email: true,\n password: true,\n number: true,\n date: true,\n month: true,\n week: true,\n time: true,\n datetime: true,\n 'datetime-local': true\n };\n\n /**\n * Helper function for legacy browsers and iframes which sometimes focus\n * elements like document, body, and non-interactive SVG.\n * @param {Element} el\n */\n function isValidFocusTarget(el) {\n if (\n el &&\n el !== document &&\n el.nodeName !== 'HTML' &&\n el.nodeName !== 'BODY' &&\n 'classList' in el &&\n 'contains' in el.classList\n ) {\n return true;\n }\n return false;\n }\n\n /**\n * Computes whether the given element should automatically trigger the\n * `focus-visible` class being added, i.e. whether it should always match\n * `:focus-visible` when focused.\n * @param {Element} el\n * @return {boolean}\n */\n function focusTriggersKeyboardModality(el) {\n var type = el.type;\n var tagName = el.tagName;\n\n if (tagName === 'INPUT' && inputTypesAllowlist[type] && !el.readOnly) {\n return true;\n }\n\n if (tagName === 'TEXTAREA' && !el.readOnly) {\n return true;\n }\n\n if (el.isContentEditable) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Add the `focus-visible` class to the given element if it was not added by\n * the author.\n * @param {Element} el\n */\n function addFocusVisibleClass(el) {\n if (el.classList.contains('focus-visible')) {\n return;\n }\n el.classList.add('focus-visible');\n el.setAttribute('data-focus-visible-added', '');\n }\n\n /**\n * Remove the `focus-visible` class from the given element if it was not\n * originally added by the author.\n * @param {Element} el\n */\n function removeFocusVisibleClass(el) {\n if (!el.hasAttribute('data-focus-visible-added')) {\n return;\n }\n el.classList.remove('focus-visible');\n el.removeAttribute('data-focus-visible-added');\n }\n\n /**\n * If the most recent user interaction was via the keyboard;\n * and the key press did not include a meta, alt/option, or control key;\n * then the modality is keyboard. Otherwise, the modality is not keyboard.\n * Apply `focus-visible` to any current active element and keep track\n * of our keyboard modality state with `hadKeyboardEvent`.\n * @param {KeyboardEvent} e\n */\n function onKeyDown(e) {\n if (e.metaKey || e.altKey || e.ctrlKey) {\n return;\n }\n\n if (isValidFocusTarget(scope.activeElement)) {\n addFocusVisibleClass(scope.activeElement);\n }\n\n hadKeyboardEvent = true;\n }\n\n /**\n * If at any point a user clicks with a pointing device, ensure that we change\n * the modality away from keyboard.\n * This avoids the situation where a user presses a key on an already focused\n * element, and then clicks on a different element, focusing it with a\n * pointing device, while we still think we're in keyboard modality.\n * @param {Event} e\n */\n function onPointerDown(e) {\n hadKeyboardEvent = false;\n }\n\n /**\n * On `focus`, add the `focus-visible` class to the target if:\n * - the target received focus as a result of keyboard navigation, or\n * - the event target is an element that will likely require interaction\n * via the keyboard (e.g. a text box)\n * @param {Event} e\n */\n function onFocus(e) {\n // Prevent IE from focusing the document or HTML element.\n if (!isValidFocusTarget(e.target)) {\n return;\n }\n\n if (hadKeyboardEvent || focusTriggersKeyboardModality(e.target)) {\n addFocusVisibleClass(e.target);\n }\n }\n\n /**\n * On `blur`, remove the `focus-visible` class from the target.\n * @param {Event} e\n */\n function onBlur(e) {\n if (!isValidFocusTarget(e.target)) {\n return;\n }\n\n if (\n e.target.classList.contains('focus-visible') ||\n e.target.hasAttribute('data-focus-visible-added')\n ) {\n // To detect a tab/window switch, we look for a blur event followed\n // rapidly by a visibility change.\n // If we don't see a visibility change within 100ms, it's probably a\n // regular focus change.\n hadFocusVisibleRecently = true;\n window.clearTimeout(hadFocusVisibleRecentlyTimeout);\n hadFocusVisibleRecentlyTimeout = window.setTimeout(function() {\n hadFocusVisibleRecently = false;\n }, 100);\n removeFocusVisibleClass(e.target);\n }\n }\n\n /**\n * If the user changes tabs, keep track of whether or not the previously\n * focused element had .focus-visible.\n * @param {Event} e\n */\n function onVisibilityChange(e) {\n if (document.visibilityState === 'hidden') {\n // If the tab becomes active again, the browser will handle calling focus\n // on the element (Safari actually calls it twice).\n // If this tab change caused a blur on an element with focus-visible,\n // re-apply the class when the user switches back to the tab.\n if (hadFocusVisibleRecently) {\n hadKeyboardEvent = true;\n }\n addInitialPointerMoveListeners();\n }\n }\n\n /**\n * Add a group of listeners to detect usage of any pointing devices.\n * These listeners will be added when the polyfill first loads, and anytime\n * the window is blurred, so that they are active when the window regains\n * focus.\n */\n function addInitialPointerMoveListeners() {\n document.addEventListener('mousemove', onInitialPointerMove);\n document.addEventListener('mousedown', onInitialPointerMove);\n document.addEventListener('mouseup', onInitialPointerMove);\n document.addEventListener('pointermove', onInitialPointerMove);\n document.addEventListener('pointerdown', onInitialPointerMove);\n document.addEventListener('pointerup', onInitialPointerMove);\n document.addEventListener('touchmove', onInitialPointerMove);\n document.addEventListener('touchstart', onInitialPointerMove);\n document.addEventListener('touchend', onInitialPointerMove);\n }\n\n function removeInitialPointerMoveListeners() {\n document.removeEventListener('mousemove', onInitialPointerMove);\n document.removeEventListener('mousedown', onInitialPointerMove);\n document.removeEventListener('mouseup', onInitialPointerMove);\n document.removeEventListener('pointermove', onInitialPointerMove);\n document.removeEventListener('pointerdown', onInitialPointerMove);\n document.removeEventListener('pointerup', onInitialPointerMove);\n document.removeEventListener('touchmove', onInitialPointerMove);\n document.removeEventListener('touchstart', onInitialPointerMove);\n document.removeEventListener('touchend', onInitialPointerMove);\n }\n\n /**\n * When the polfyill first loads, assume the user is in keyboard modality.\n * If any event is received from a pointing device (e.g. mouse, pointer,\n * touch), turn off keyboard modality.\n * This accounts for situations where focus enters the page from the URL bar.\n * @param {Event} e\n */\n function onInitialPointerMove(e) {\n // Work around a Safari quirk that fires a mousemove on whenever the\n // window blurs, even if you're tabbing out of the page. \u00AF\\_(\u30C4)_/\u00AF\n if (e.target.nodeName && e.target.nodeName.toLowerCase() === 'html') {\n return;\n }\n\n hadKeyboardEvent = false;\n removeInitialPointerMoveListeners();\n }\n\n // For some kinds of state, we are interested in changes at the global scope\n // only. For example, global pointer input, global key presses and global\n // visibility change should affect the state at every scope:\n document.addEventListener('keydown', onKeyDown, true);\n document.addEventListener('mousedown', onPointerDown, true);\n document.addEventListener('pointerdown', onPointerDown, true);\n document.addEventListener('touchstart', onPointerDown, true);\n document.addEventListener('visibilitychange', onVisibilityChange, true);\n\n addInitialPointerMoveListeners();\n\n // For focus and blur, we specifically care about state changes in the local\n // scope. This is because focus / blur events that originate from within a\n // shadow root are not re-dispatched from the host element if it was already\n // the active element in its own scope:\n scope.addEventListener('focus', onFocus, true);\n scope.addEventListener('blur', onBlur, true);\n\n // We detect that a node is a ShadowRoot by ensuring that it is a\n // DocumentFragment and also has a host property. This check covers native\n // implementation and polyfill implementation transparently. If we only cared\n // about the native implementation, we could just check if the scope was\n // an instance of a ShadowRoot.\n if (scope.nodeType === Node.DOCUMENT_FRAGMENT_NODE && scope.host) {\n // Since a ShadowRoot is a special kind of DocumentFragment, it does not\n // have a root element to add a class to. So, we add this attribute to the\n // host element instead:\n scope.host.setAttribute('data-js-focus-visible', '');\n } else if (scope.nodeType === Node.DOCUMENT_NODE) {\n document.documentElement.classList.add('js-focus-visible');\n document.documentElement.setAttribute('data-js-focus-visible', '');\n }\n }\n\n // It is important to wrap all references to global window and document in\n // these checks to support server-side rendering use cases\n // @see https://github.com/WICG/focus-visible/issues/199\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n // Make the polyfill helper globally available. This can be used as a signal\n // to interested libraries that wish to coordinate with the polyfill for e.g.,\n // applying the polyfill to a shadow root:\n window.applyFocusVisiblePolyfill = applyFocusVisiblePolyfill;\n\n // Notify interested libraries of the polyfill's presence, in case the\n // polyfill was loaded lazily:\n var event;\n\n try {\n event = new CustomEvent('focus-visible-polyfill-ready');\n } catch (error) {\n // IE11 does not support using CustomEvent as a constructor directly:\n event = document.createEvent('CustomEvent');\n event.initCustomEvent('focus-visible-polyfill-ready', false, false, {});\n }\n\n window.dispatchEvent(event);\n }\n\n if (typeof document !== 'undefined') {\n // Apply the polyfill to the global document, so that no JavaScript\n // coordination is required to use the polyfill in the top-level document:\n applyFocusVisiblePolyfill(document);\n }\n\n})));\n", "/*!\n * escape-html\n * Copyright(c) 2012-2013 TJ Holowaychuk\n * Copyright(c) 2015 Andreas Lubbe\n * Copyright(c) 2015 Tiancheng \"Timothy\" Gu\n * MIT Licensed\n */\n\n'use strict';\n\n/**\n * Module variables.\n * @private\n */\n\nvar matchHtmlRegExp = /[\"'&<>]/;\n\n/**\n * Module exports.\n * @public\n */\n\nmodule.exports = escapeHtml;\n\n/**\n * Escape special characters in the given string of html.\n *\n * @param {string} string The string to escape for inserting into HTML\n * @return {string}\n * @public\n */\n\nfunction escapeHtml(string) {\n var str = '' + string;\n var match = matchHtmlRegExp.exec(str);\n\n if (!match) {\n return str;\n }\n\n var escape;\n var html = '';\n var index = 0;\n var lastIndex = 0;\n\n for (index = match.index; index < str.length; index++) {\n switch (str.charCodeAt(index)) {\n case 34: // \"\n escape = '"';\n break;\n case 38: // &\n escape = '&';\n break;\n case 39: // '\n escape = ''';\n break;\n case 60: // <\n escape = '<';\n break;\n case 62: // >\n escape = '>';\n break;\n default:\n continue;\n }\n\n if (lastIndex !== index) {\n html += str.substring(lastIndex, index);\n }\n\n lastIndex = index + 1;\n html += escape;\n }\n\n return lastIndex !== index\n ? html + str.substring(lastIndex, index)\n : html;\n}\n", "/*!\n * clipboard.js v2.0.11\n * https://clipboardjs.com/\n *\n * Licensed MIT \u00A9 Zeno Rocha\n */\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ClipboardJS\"] = factory();\n\telse\n\t\troot[\"ClipboardJS\"] = factory();\n})(this, function() {\nreturn /******/ (function() { // webpackBootstrap\n/******/ \tvar __webpack_modules__ = ({\n\n/***/ 686:\n/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n \"default\": function() { return /* binding */ clipboard; }\n});\n\n// EXTERNAL MODULE: ./node_modules/tiny-emitter/index.js\nvar tiny_emitter = __webpack_require__(279);\nvar tiny_emitter_default = /*#__PURE__*/__webpack_require__.n(tiny_emitter);\n// EXTERNAL MODULE: ./node_modules/good-listener/src/listen.js\nvar listen = __webpack_require__(370);\nvar listen_default = /*#__PURE__*/__webpack_require__.n(listen);\n// EXTERNAL MODULE: ./node_modules/select/src/select.js\nvar src_select = __webpack_require__(817);\nvar select_default = /*#__PURE__*/__webpack_require__.n(src_select);\n;// CONCATENATED MODULE: ./src/common/command.js\n/**\n * Executes a given operation type.\n * @param {String} type\n * @return {Boolean}\n */\nfunction command(type) {\n try {\n return document.execCommand(type);\n } catch (err) {\n return false;\n }\n}\n;// CONCATENATED MODULE: ./src/actions/cut.js\n\n\n/**\n * Cut action wrapper.\n * @param {String|HTMLElement} target\n * @return {String}\n */\n\nvar ClipboardActionCut = function ClipboardActionCut(target) {\n var selectedText = select_default()(target);\n command('cut');\n return selectedText;\n};\n\n/* harmony default export */ var actions_cut = (ClipboardActionCut);\n;// CONCATENATED MODULE: ./src/common/create-fake-element.js\n/**\n * Creates a fake textarea element with a value.\n * @param {String} value\n * @return {HTMLElement}\n */\nfunction createFakeElement(value) {\n var isRTL = document.documentElement.getAttribute('dir') === 'rtl';\n var fakeElement = document.createElement('textarea'); // Prevent zooming on iOS\n\n fakeElement.style.fontSize = '12pt'; // Reset box model\n\n fakeElement.style.border = '0';\n fakeElement.style.padding = '0';\n fakeElement.style.margin = '0'; // Move element out of screen horizontally\n\n fakeElement.style.position = 'absolute';\n fakeElement.style[isRTL ? 'right' : 'left'] = '-9999px'; // Move element to the same position vertically\n\n var yPosition = window.pageYOffset || document.documentElement.scrollTop;\n fakeElement.style.top = \"\".concat(yPosition, \"px\");\n fakeElement.setAttribute('readonly', '');\n fakeElement.value = value;\n return fakeElement;\n}\n;// CONCATENATED MODULE: ./src/actions/copy.js\n\n\n\n/**\n * Create fake copy action wrapper using a fake element.\n * @param {String} target\n * @param {Object} options\n * @return {String}\n */\n\nvar fakeCopyAction = function fakeCopyAction(value, options) {\n var fakeElement = createFakeElement(value);\n options.container.appendChild(fakeElement);\n var selectedText = select_default()(fakeElement);\n command('copy');\n fakeElement.remove();\n return selectedText;\n};\n/**\n * Copy action wrapper.\n * @param {String|HTMLElement} target\n * @param {Object} options\n * @return {String}\n */\n\n\nvar ClipboardActionCopy = function ClipboardActionCopy(target) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n container: document.body\n };\n var selectedText = '';\n\n if (typeof target === 'string') {\n selectedText = fakeCopyAction(target, options);\n } else if (target instanceof HTMLInputElement && !['text', 'search', 'url', 'tel', 'password'].includes(target === null || target === void 0 ? void 0 : target.type)) {\n // If input type doesn't support `setSelectionRange`. Simulate it. https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange\n selectedText = fakeCopyAction(target.value, options);\n } else {\n selectedText = select_default()(target);\n command('copy');\n }\n\n return selectedText;\n};\n\n/* harmony default export */ var actions_copy = (ClipboardActionCopy);\n;// CONCATENATED MODULE: ./src/actions/default.js\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\n\n\n/**\n * Inner function which performs selection from either `text` or `target`\n * properties and then executes copy or cut operations.\n * @param {Object} options\n */\n\nvar ClipboardActionDefault = function ClipboardActionDefault() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n // Defines base properties passed from constructor.\n var _options$action = options.action,\n action = _options$action === void 0 ? 'copy' : _options$action,\n container = options.container,\n target = options.target,\n text = options.text; // Sets the `action` to be performed which can be either 'copy' or 'cut'.\n\n if (action !== 'copy' && action !== 'cut') {\n throw new Error('Invalid \"action\" value, use either \"copy\" or \"cut\"');\n } // Sets the `target` property using an element that will be have its content copied.\n\n\n if (target !== undefined) {\n if (target && _typeof(target) === 'object' && target.nodeType === 1) {\n if (action === 'copy' && target.hasAttribute('disabled')) {\n throw new Error('Invalid \"target\" attribute. Please use \"readonly\" instead of \"disabled\" attribute');\n }\n\n if (action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {\n throw new Error('Invalid \"target\" attribute. You can\\'t cut text from elements with \"readonly\" or \"disabled\" attributes');\n }\n } else {\n throw new Error('Invalid \"target\" value, use a valid Element');\n }\n } // Define selection strategy based on `text` property.\n\n\n if (text) {\n return actions_copy(text, {\n container: container\n });\n } // Defines which selection strategy based on `target` property.\n\n\n if (target) {\n return action === 'cut' ? actions_cut(target) : actions_copy(target, {\n container: container\n });\n }\n};\n\n/* harmony default export */ var actions_default = (ClipboardActionDefault);\n;// CONCATENATED MODULE: ./src/clipboard.js\nfunction clipboard_typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { clipboard_typeof = function _typeof(obj) { return typeof obj; }; } else { clipboard_typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return clipboard_typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (clipboard_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n\n\n\n\n\n/**\n * Helper function to retrieve attribute value.\n * @param {String} suffix\n * @param {Element} element\n */\n\nfunction getAttributeValue(suffix, element) {\n var attribute = \"data-clipboard-\".concat(suffix);\n\n if (!element.hasAttribute(attribute)) {\n return;\n }\n\n return element.getAttribute(attribute);\n}\n/**\n * Base class which takes one or more elements, adds event listeners to them,\n * and instantiates a new `ClipboardAction` on each click.\n */\n\n\nvar Clipboard = /*#__PURE__*/function (_Emitter) {\n _inherits(Clipboard, _Emitter);\n\n var _super = _createSuper(Clipboard);\n\n /**\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n * @param {Object} options\n */\n function Clipboard(trigger, options) {\n var _this;\n\n _classCallCheck(this, Clipboard);\n\n _this = _super.call(this);\n\n _this.resolveOptions(options);\n\n _this.listenClick(trigger);\n\n return _this;\n }\n /**\n * Defines if attributes would be resolved using internal setter functions\n * or custom functions that were passed in the constructor.\n * @param {Object} options\n */\n\n\n _createClass(Clipboard, [{\n key: \"resolveOptions\",\n value: function resolveOptions() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n this.action = typeof options.action === 'function' ? options.action : this.defaultAction;\n this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;\n this.text = typeof options.text === 'function' ? options.text : this.defaultText;\n this.container = clipboard_typeof(options.container) === 'object' ? options.container : document.body;\n }\n /**\n * Adds a click event listener to the passed trigger.\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n */\n\n }, {\n key: \"listenClick\",\n value: function listenClick(trigger) {\n var _this2 = this;\n\n this.listener = listen_default()(trigger, 'click', function (e) {\n return _this2.onClick(e);\n });\n }\n /**\n * Defines a new `ClipboardAction` on each click event.\n * @param {Event} e\n */\n\n }, {\n key: \"onClick\",\n value: function onClick(e) {\n var trigger = e.delegateTarget || e.currentTarget;\n var action = this.action(trigger) || 'copy';\n var text = actions_default({\n action: action,\n container: this.container,\n target: this.target(trigger),\n text: this.text(trigger)\n }); // Fires an event based on the copy operation result.\n\n this.emit(text ? 'success' : 'error', {\n action: action,\n text: text,\n trigger: trigger,\n clearSelection: function clearSelection() {\n if (trigger) {\n trigger.focus();\n }\n\n window.getSelection().removeAllRanges();\n }\n });\n }\n /**\n * Default `action` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: \"defaultAction\",\n value: function defaultAction(trigger) {\n return getAttributeValue('action', trigger);\n }\n /**\n * Default `target` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: \"defaultTarget\",\n value: function defaultTarget(trigger) {\n var selector = getAttributeValue('target', trigger);\n\n if (selector) {\n return document.querySelector(selector);\n }\n }\n /**\n * Allow fire programmatically a copy action\n * @param {String|HTMLElement} target\n * @param {Object} options\n * @returns Text copied.\n */\n\n }, {\n key: \"defaultText\",\n\n /**\n * Default `text` lookup function.\n * @param {Element} trigger\n */\n value: function defaultText(trigger) {\n return getAttributeValue('text', trigger);\n }\n /**\n * Destroy lifecycle.\n */\n\n }, {\n key: \"destroy\",\n value: function destroy() {\n this.listener.destroy();\n }\n }], [{\n key: \"copy\",\n value: function copy(target) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n container: document.body\n };\n return actions_copy(target, options);\n }\n /**\n * Allow fire programmatically a cut action\n * @param {String|HTMLElement} target\n * @returns Text cutted.\n */\n\n }, {\n key: \"cut\",\n value: function cut(target) {\n return actions_cut(target);\n }\n /**\n * Returns the support of the given action, or all actions if no action is\n * given.\n * @param {String} [action]\n */\n\n }, {\n key: \"isSupported\",\n value: function isSupported() {\n var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['copy', 'cut'];\n var actions = typeof action === 'string' ? [action] : action;\n var support = !!document.queryCommandSupported;\n actions.forEach(function (action) {\n support = support && !!document.queryCommandSupported(action);\n });\n return support;\n }\n }]);\n\n return Clipboard;\n}((tiny_emitter_default()));\n\n/* harmony default export */ var clipboard = (Clipboard);\n\n/***/ }),\n\n/***/ 828:\n/***/ (function(module) {\n\nvar DOCUMENT_NODE_TYPE = 9;\n\n/**\n * A polyfill for Element.matches()\n */\nif (typeof Element !== 'undefined' && !Element.prototype.matches) {\n var proto = Element.prototype;\n\n proto.matches = proto.matchesSelector ||\n proto.mozMatchesSelector ||\n proto.msMatchesSelector ||\n proto.oMatchesSelector ||\n proto.webkitMatchesSelector;\n}\n\n/**\n * Finds the closest parent that matches a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @return {Function}\n */\nfunction closest (element, selector) {\n while (element && element.nodeType !== DOCUMENT_NODE_TYPE) {\n if (typeof element.matches === 'function' &&\n element.matches(selector)) {\n return element;\n }\n element = element.parentNode;\n }\n}\n\nmodule.exports = closest;\n\n\n/***/ }),\n\n/***/ 438:\n/***/ (function(module, __unused_webpack_exports, __webpack_require__) {\n\nvar closest = __webpack_require__(828);\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction _delegate(element, selector, type, callback, useCapture) {\n var listenerFn = listener.apply(this, arguments);\n\n element.addEventListener(type, listenerFn, useCapture);\n\n return {\n destroy: function() {\n element.removeEventListener(type, listenerFn, useCapture);\n }\n }\n}\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element|String|Array} [elements]\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction delegate(elements, selector, type, callback, useCapture) {\n // Handle the regular Element usage\n if (typeof elements.addEventListener === 'function') {\n return _delegate.apply(null, arguments);\n }\n\n // Handle Element-less usage, it defaults to global delegation\n if (typeof type === 'function') {\n // Use `document` as the first parameter, then apply arguments\n // This is a short way to .unshift `arguments` without running into deoptimizations\n return _delegate.bind(null, document).apply(null, arguments);\n }\n\n // Handle Selector-based usage\n if (typeof elements === 'string') {\n elements = document.querySelectorAll(elements);\n }\n\n // Handle Array-like based usage\n return Array.prototype.map.call(elements, function (element) {\n return _delegate(element, selector, type, callback, useCapture);\n });\n}\n\n/**\n * Finds closest match and invokes callback.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Function}\n */\nfunction listener(element, selector, type, callback) {\n return function(e) {\n e.delegateTarget = closest(e.target, selector);\n\n if (e.delegateTarget) {\n callback.call(element, e);\n }\n }\n}\n\nmodule.exports = delegate;\n\n\n/***/ }),\n\n/***/ 879:\n/***/ (function(__unused_webpack_module, exports) {\n\n/**\n * Check if argument is a HTML element.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.node = function(value) {\n return value !== undefined\n && value instanceof HTMLElement\n && value.nodeType === 1;\n};\n\n/**\n * Check if argument is a list of HTML elements.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.nodeList = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return value !== undefined\n && (type === '[object NodeList]' || type === '[object HTMLCollection]')\n && ('length' in value)\n && (value.length === 0 || exports.node(value[0]));\n};\n\n/**\n * Check if argument is a string.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.string = function(value) {\n return typeof value === 'string'\n || value instanceof String;\n};\n\n/**\n * Check if argument is a function.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.fn = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return type === '[object Function]';\n};\n\n\n/***/ }),\n\n/***/ 370:\n/***/ (function(module, __unused_webpack_exports, __webpack_require__) {\n\nvar is = __webpack_require__(879);\nvar delegate = __webpack_require__(438);\n\n/**\n * Validates all params and calls the right\n * listener function based on its target type.\n *\n * @param {String|HTMLElement|HTMLCollection|NodeList} target\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listen(target, type, callback) {\n if (!target && !type && !callback) {\n throw new Error('Missing required arguments');\n }\n\n if (!is.string(type)) {\n throw new TypeError('Second argument must be a String');\n }\n\n if (!is.fn(callback)) {\n throw new TypeError('Third argument must be a Function');\n }\n\n if (is.node(target)) {\n return listenNode(target, type, callback);\n }\n else if (is.nodeList(target)) {\n return listenNodeList(target, type, callback);\n }\n else if (is.string(target)) {\n return listenSelector(target, type, callback);\n }\n else {\n throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');\n }\n}\n\n/**\n * Adds an event listener to a HTML element\n * and returns a remove listener function.\n *\n * @param {HTMLElement} node\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNode(node, type, callback) {\n node.addEventListener(type, callback);\n\n return {\n destroy: function() {\n node.removeEventListener(type, callback);\n }\n }\n}\n\n/**\n * Add an event listener to a list of HTML elements\n * and returns a remove listener function.\n *\n * @param {NodeList|HTMLCollection} nodeList\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNodeList(nodeList, type, callback) {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.addEventListener(type, callback);\n });\n\n return {\n destroy: function() {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.removeEventListener(type, callback);\n });\n }\n }\n}\n\n/**\n * Add an event listener to a selector\n * and returns a remove listener function.\n *\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenSelector(selector, type, callback) {\n return delegate(document.body, selector, type, callback);\n}\n\nmodule.exports = listen;\n\n\n/***/ }),\n\n/***/ 817:\n/***/ (function(module) {\n\nfunction select(element) {\n var selectedText;\n\n if (element.nodeName === 'SELECT') {\n element.focus();\n\n selectedText = element.value;\n }\n else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {\n var isReadOnly = element.hasAttribute('readonly');\n\n if (!isReadOnly) {\n element.setAttribute('readonly', '');\n }\n\n element.select();\n element.setSelectionRange(0, element.value.length);\n\n if (!isReadOnly) {\n element.removeAttribute('readonly');\n }\n\n selectedText = element.value;\n }\n else {\n if (element.hasAttribute('contenteditable')) {\n element.focus();\n }\n\n var selection = window.getSelection();\n var range = document.createRange();\n\n range.selectNodeContents(element);\n selection.removeAllRanges();\n selection.addRange(range);\n\n selectedText = selection.toString();\n }\n\n return selectedText;\n}\n\nmodule.exports = select;\n\n\n/***/ }),\n\n/***/ 279:\n/***/ (function(module) {\n\nfunction E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n};\n\nmodule.exports = E;\nmodule.exports.TinyEmitter = E;\n\n\n/***/ })\n\n/******/ \t});\n/************************************************************************/\n/******/ \t// The module cache\n/******/ \tvar __webpack_module_cache__ = {};\n/******/ \t\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(__webpack_module_cache__[moduleId]) {\n/******/ \t\t\treturn __webpack_module_cache__[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = __webpack_module_cache__[moduleId] = {\n/******/ \t\t\t// no module.id needed\n/******/ \t\t\t// no module.loaded needed\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/ \t\n/******/ \t\t// Execute the module function\n/******/ \t\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n/******/ \t\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/ \t\n/************************************************************************/\n/******/ \t/* webpack/runtime/compat get default export */\n/******/ \t!function() {\n/******/ \t\t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t\t__webpack_require__.n = function(module) {\n/******/ \t\t\tvar getter = module && module.__esModule ?\n/******/ \t\t\t\tfunction() { return module['default']; } :\n/******/ \t\t\t\tfunction() { return module; };\n/******/ \t\t\t__webpack_require__.d(getter, { a: getter });\n/******/ \t\t\treturn getter;\n/******/ \t\t};\n/******/ \t}();\n/******/ \t\n/******/ \t/* webpack/runtime/define property getters */\n/******/ \t!function() {\n/******/ \t\t// define getter functions for harmony exports\n/******/ \t\t__webpack_require__.d = function(exports, definition) {\n/******/ \t\t\tfor(var key in definition) {\n/******/ \t\t\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n/******/ \t\t\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n/******/ \t\t\t\t}\n/******/ \t\t\t}\n/******/ \t\t};\n/******/ \t}();\n/******/ \t\n/******/ \t/* webpack/runtime/hasOwnProperty shorthand */\n/******/ \t!function() {\n/******/ \t\t__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }\n/******/ \t}();\n/******/ \t\n/************************************************************************/\n/******/ \t// module exports must be returned from runtime so entry inlining is disabled\n/******/ \t// startup\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(686);\n/******/ })()\n.default;\n});", "/*\n * Copyright (c) 2016-2025 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport \"focus-visible\"\n\nimport {\n EMPTY,\n NEVER,\n Observable,\n Subject,\n defer,\n delay,\n filter,\n map,\n merge,\n mergeWith,\n shareReplay,\n switchMap\n} from \"rxjs\"\n\nimport { configuration, feature } from \"./_\"\nimport {\n at,\n getActiveElement,\n getOptionalElement,\n requestJSON,\n setLocation,\n setToggle,\n watchDocument,\n watchKeyboard,\n watchLocation,\n watchLocationTarget,\n watchMedia,\n watchPrint,\n watchScript,\n watchViewport\n} from \"./browser\"\nimport {\n getComponentElement,\n getComponentElements,\n mountAnnounce,\n mountBackToTop,\n mountConsent,\n mountContent,\n mountDialog,\n mountHeader,\n mountHeaderTitle,\n mountPalette,\n mountProgress,\n mountSearch,\n mountSearchHiglight,\n mountSidebar,\n mountSource,\n mountTableOfContents,\n mountTabs,\n watchHeader,\n watchMain\n} from \"./components\"\nimport {\n SearchIndex,\n setupClipboardJS,\n setupInstantNavigation,\n setupVersionSelector\n} from \"./integrations\"\nimport {\n patchEllipsis,\n patchIndeterminate,\n patchScrollfix,\n patchScrolllock\n} from \"./patches\"\nimport \"./polyfills\"\n\n/* ----------------------------------------------------------------------------\n * Functions - @todo refactor\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch search index\n *\n * @returns Search index observable\n */\nfunction fetchSearchIndex(): Observable {\n if (location.protocol === \"file:\") {\n return watchScript(\n `${new URL(\"search/search_index.js\", config.base)}`\n )\n .pipe(\n // @ts-ignore - @todo fix typings\n map(() => __index),\n shareReplay(1)\n )\n } else {\n return requestJSON(\n new URL(\"search/search_index.json\", config.base)\n )\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Application\n * ------------------------------------------------------------------------- */\n\n/* Yay, JavaScript is available */\ndocument.documentElement.classList.remove(\"no-js\")\ndocument.documentElement.classList.add(\"js\")\n\n/* Set up navigation observables and subjects */\nconst document$ = watchDocument()\nconst location$ = watchLocation()\nconst target$ = watchLocationTarget(location$)\nconst keyboard$ = watchKeyboard()\n\n/* Set up media observables */\nconst viewport$ = watchViewport()\nconst tablet$ = watchMedia(\"(min-width: 960px)\")\nconst screen$ = watchMedia(\"(min-width: 1220px)\")\nconst print$ = watchPrint()\n\n/* Retrieve search index, if search is enabled */\nconst config = configuration()\nconst index$ = document.forms.namedItem(\"search\")\n ? fetchSearchIndex()\n : NEVER\n\n/* Set up Clipboard.js integration */\nconst alert$ = new Subject()\nsetupClipboardJS({ alert$ })\n\n/* Set up progress indicator */\nconst progress$ = new Subject()\n\n/* Set up instant navigation, if enabled */\nif (feature(\"navigation.instant\"))\n setupInstantNavigation({ location$, viewport$, progress$ })\n .subscribe(document$)\n\n/* Set up version selector */\nif (config.version?.provider === \"mike\")\n setupVersionSelector({ document$ })\n\n/* Always close drawer and search on navigation */\nmerge(location$, target$)\n .pipe(\n delay(125)\n )\n .subscribe(() => {\n setToggle(\"drawer\", false)\n setToggle(\"search\", false)\n })\n\n/* Set up global keyboard handlers */\nkeyboard$\n .pipe(\n filter(({ mode }) => mode === \"global\")\n )\n .subscribe(key => {\n switch (key.type) {\n\n /* Go to previous page */\n case \"p\":\n case \",\":\n const prev = getOptionalElement(\"link[rel=prev]\")\n if (typeof prev !== \"undefined\")\n setLocation(prev)\n break\n\n /* Go to next page */\n case \"n\":\n case \".\":\n const next = getOptionalElement(\"link[rel=next]\")\n if (typeof next !== \"undefined\")\n setLocation(next)\n break\n\n /* Expand navigation, see https://bit.ly/3ZjG5io */\n case \"Enter\":\n const active = getActiveElement()\n if (active instanceof HTMLLabelElement)\n active.click()\n }\n })\n\n/* Set up patches */\npatchEllipsis({ viewport$, document$ })\npatchIndeterminate({ document$, tablet$ })\npatchScrollfix({ document$ })\npatchScrolllock({ viewport$, tablet$ })\n\n/* Set up header and main area observable */\nconst header$ = watchHeader(getComponentElement(\"header\"), { viewport$ })\nconst main$ = document$\n .pipe(\n map(() => getComponentElement(\"main\")),\n switchMap(el => watchMain(el, { viewport$, header$ })),\n shareReplay(1)\n )\n\n/* Set up control component observables */\nconst control$ = merge(\n\n /* Consent */\n ...getComponentElements(\"consent\")\n .map(el => mountConsent(el, { target$ })),\n\n /* Dialog */\n ...getComponentElements(\"dialog\")\n .map(el => mountDialog(el, { alert$ })),\n\n /* Color palette */\n ...getComponentElements(\"palette\")\n .map(el => mountPalette(el)),\n\n /* Progress bar */\n ...getComponentElements(\"progress\")\n .map(el => mountProgress(el, { progress$ })),\n\n /* Search */\n ...getComponentElements(\"search\")\n .map(el => mountSearch(el, { index$, keyboard$ })),\n\n /* Repository information */\n ...getComponentElements(\"source\")\n .map(el => mountSource(el))\n)\n\n/* Set up content component observables */\nconst content$ = defer(() => merge(\n\n /* Announcement bar */\n ...getComponentElements(\"announce\")\n .map(el => mountAnnounce(el)),\n\n /* Content */\n ...getComponentElements(\"content\")\n .map(el => mountContent(el, { viewport$, target$, print$ })),\n\n /* Search highlighting */\n ...getComponentElements(\"content\")\n .map(el => feature(\"search.highlight\")\n ? mountSearchHiglight(el, { index$, location$ })\n : EMPTY\n ),\n\n /* Header */\n ...getComponentElements(\"header\")\n .map(el => mountHeader(el, { viewport$, header$, main$ })),\n\n /* Header title */\n ...getComponentElements(\"header-title\")\n .map(el => mountHeaderTitle(el, { viewport$, header$ })),\n\n /* Sidebar */\n ...getComponentElements(\"sidebar\")\n .map(el => el.getAttribute(\"data-md-type\") === \"navigation\"\n ? at(screen$, () => mountSidebar(el, { viewport$, header$, main$ }))\n : at(tablet$, () => mountSidebar(el, { viewport$, header$, main$ }))\n ),\n\n /* Navigation tabs */\n ...getComponentElements(\"tabs\")\n .map(el => mountTabs(el, { viewport$, header$ })),\n\n /* Table of contents */\n ...getComponentElements(\"toc\")\n .map(el => mountTableOfContents(el, {\n viewport$, header$, main$, target$\n })),\n\n /* Back-to-top button */\n ...getComponentElements(\"top\")\n .map(el => mountBackToTop(el, { viewport$, header$, main$, target$ }))\n))\n\n/* Set up component observables */\nconst component$ = document$\n .pipe(\n switchMap(() => content$),\n mergeWith(control$),\n shareReplay(1)\n )\n\n/* Subscribe to all components */\ncomponent$.subscribe()\n\n/* ----------------------------------------------------------------------------\n * Exports\n * ------------------------------------------------------------------------- */\n\nwindow.document$ = document$ /* Document observable */\nwindow.location$ = location$ /* Location subject */\nwindow.target$ = target$ /* Location target observable */\nwindow.keyboard$ = keyboard$ /* Keyboard observable */\nwindow.viewport$ = viewport$ /* Viewport observable */\nwindow.tablet$ = tablet$ /* Media tablet observable */\nwindow.screen$ = screen$ /* Media screen observable */\nwindow.print$ = print$ /* Media print observable */\nwindow.alert$ = alert$ /* Alert subject */\nwindow.progress$ = progress$ /* Progress indicator subject */\nwindow.component$ = component$ /* Component observable */\n", "/******************************************************************************\nCopyright (c) Microsoft Corporation.\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\nPERFORMANCE OF THIS SOFTWARE.\n***************************************************************************** */\n/* global Reflect, Promise, SuppressedError, Symbol, Iterator */\n\nvar extendStatics = function(d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\n return extendStatics(d, b);\n};\n\nexport function __extends(d, b) {\n if (typeof b !== \"function\" && b !== null)\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n}\n\nexport var __assign = function() {\n __assign = Object.assign || function __assign(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\n }\n return t;\n }\n return __assign.apply(this, arguments);\n}\n\nexport function __rest(s, e) {\n var t = {};\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\n t[p] = s[p];\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\n t[p[i]] = s[p[i]];\n }\n return t;\n}\n\nexport function __decorate(decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n}\n\nexport function __param(paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n}\n\nexport function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {\n function accept(f) { if (f !== void 0 && typeof f !== \"function\") throw new TypeError(\"Function expected\"); return f; }\n var kind = contextIn.kind, key = kind === \"getter\" ? \"get\" : kind === \"setter\" ? \"set\" : \"value\";\n var target = !descriptorIn && ctor ? contextIn[\"static\"] ? ctor : ctor.prototype : null;\n var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});\n var _, done = false;\n for (var i = decorators.length - 1; i >= 0; i--) {\n var context = {};\n for (var p in contextIn) context[p] = p === \"access\" ? {} : contextIn[p];\n for (var p in contextIn.access) context.access[p] = contextIn.access[p];\n context.addInitializer = function (f) { if (done) throw new TypeError(\"Cannot add initializers after decoration has completed\"); extraInitializers.push(accept(f || null)); };\n var result = (0, decorators[i])(kind === \"accessor\" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);\n if (kind === \"accessor\") {\n if (result === void 0) continue;\n if (result === null || typeof result !== \"object\") throw new TypeError(\"Object expected\");\n if (_ = accept(result.get)) descriptor.get = _;\n if (_ = accept(result.set)) descriptor.set = _;\n if (_ = accept(result.init)) initializers.unshift(_);\n }\n else if (_ = accept(result)) {\n if (kind === \"field\") initializers.unshift(_);\n else descriptor[key] = _;\n }\n }\n if (target) Object.defineProperty(target, contextIn.name, descriptor);\n done = true;\n};\n\nexport function __runInitializers(thisArg, initializers, value) {\n var useValue = arguments.length > 2;\n for (var i = 0; i < initializers.length; i++) {\n value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);\n }\n return useValue ? value : void 0;\n};\n\nexport function __propKey(x) {\n return typeof x === \"symbol\" ? x : \"\".concat(x);\n};\n\nexport function __setFunctionName(f, name, prefix) {\n if (typeof name === \"symbol\") name = name.description ? \"[\".concat(name.description, \"]\") : \"\";\n return Object.defineProperty(f, \"name\", { configurable: true, value: prefix ? \"\".concat(prefix, \" \", name) : name });\n};\n\nexport function __metadata(metadataKey, metadataValue) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\n}\n\nexport function __awaiter(thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n}\n\nexport function __generator(thisArg, body) {\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === \"function\" ? Iterator : Object).prototype);\n return g.next = verb(0), g[\"throw\"] = verb(1), g[\"return\"] = verb(2), typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n function verb(n) { return function (v) { return step([n, v]); }; }\n function step(op) {\n if (f) throw new TypeError(\"Generator is already executing.\");\n while (g && (g = 0, op[0] && (_ = 0)), _) try {\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n if (y = 0, t) op = [op[0] & 2, t.value];\n switch (op[0]) {\n case 0: case 1: t = op; break;\n case 4: _.label++; return { value: op[1], done: false };\n case 5: _.label++; y = op[1]; op = [0]; continue;\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n if (t[2]) _.ops.pop();\n _.trys.pop(); continue;\n }\n op = body.call(thisArg, _);\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n }\n}\n\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n});\n\nexport function __exportStar(m, o) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\n}\n\nexport function __values(o) {\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\n if (m) return m.call(o);\n if (o && typeof o.length === \"number\") return {\n next: function () {\n if (o && i >= o.length) o = void 0;\n return { value: o && o[i++], done: !o };\n }\n };\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\n}\n\nexport function __read(o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n}\n\n/** @deprecated */\nexport function __spread() {\n for (var ar = [], i = 0; i < arguments.length; i++)\n ar = ar.concat(__read(arguments[i]));\n return ar;\n}\n\n/** @deprecated */\nexport function __spreadArrays() {\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\n r[k] = a[j];\n return r;\n}\n\nexport function __spreadArray(to, from, pack) {\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\n if (ar || !(i in from)) {\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\n ar[i] = from[i];\n }\n }\n return to.concat(ar || Array.prototype.slice.call(from));\n}\n\nexport function __await(v) {\n return this instanceof __await ? (this.v = v, this) : new __await(v);\n}\n\nexport function __asyncGenerator(thisArg, _arguments, generator) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\n return i = Object.create((typeof AsyncIterator === \"function\" ? AsyncIterator : Object).prototype), verb(\"next\"), verb(\"throw\"), verb(\"return\", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;\n function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }\n function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\n function fulfill(value) { resume(\"next\", value); }\n function reject(value) { resume(\"throw\", value); }\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\n}\n\nexport function __asyncDelegator(o) {\n var i, p;\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }\n}\n\nexport function __asyncValues(o) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var m = o[Symbol.asyncIterator], i;\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\n}\n\nexport function __makeTemplateObject(cooked, raw) {\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\n return cooked;\n};\n\nvar __setModuleDefault = Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n};\n\nexport function __importStar(mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n}\n\nexport function __importDefault(mod) {\n return (mod && mod.__esModule) ? mod : { default: mod };\n}\n\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\n}\n\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\n}\n\nexport function __classPrivateFieldIn(state, receiver) {\n if (receiver === null || (typeof receiver !== \"object\" && typeof receiver !== \"function\")) throw new TypeError(\"Cannot use 'in' operator on non-object\");\n return typeof state === \"function\" ? receiver === state : state.has(receiver);\n}\n\nexport function __addDisposableResource(env, value, async) {\n if (value !== null && value !== void 0) {\n if (typeof value !== \"object\" && typeof value !== \"function\") throw new TypeError(\"Object expected.\");\n var dispose, inner;\n if (async) {\n if (!Symbol.asyncDispose) throw new TypeError(\"Symbol.asyncDispose is not defined.\");\n dispose = value[Symbol.asyncDispose];\n }\n if (dispose === void 0) {\n if (!Symbol.dispose) throw new TypeError(\"Symbol.dispose is not defined.\");\n dispose = value[Symbol.dispose];\n if (async) inner = dispose;\n }\n if (typeof dispose !== \"function\") throw new TypeError(\"Object not disposable.\");\n if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };\n env.stack.push({ value: value, dispose: dispose, async: async });\n }\n else if (async) {\n env.stack.push({ async: true });\n }\n return value;\n}\n\nvar _SuppressedError = typeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\n var e = new Error(message);\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\n};\n\nexport function __disposeResources(env) {\n function fail(e) {\n env.error = env.hasError ? new _SuppressedError(e, env.error, \"An error was suppressed during disposal.\") : e;\n env.hasError = true;\n }\n var r, s = 0;\n function next() {\n while (r = env.stack.pop()) {\n try {\n if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);\n if (r.dispose) {\n var result = r.dispose.call(r.value);\n if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });\n }\n else s |= 1;\n }\n catch (e) {\n fail(e);\n }\n }\n if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();\n if (env.hasError) throw env.error;\n }\n return next();\n}\n\nexport default {\n __extends,\n __assign,\n __rest,\n __decorate,\n __param,\n __metadata,\n __awaiter,\n __generator,\n __createBinding,\n __exportStar,\n __values,\n __read,\n __spread,\n __spreadArrays,\n __spreadArray,\n __await,\n __asyncGenerator,\n __asyncDelegator,\n __asyncValues,\n __makeTemplateObject,\n __importStar,\n __importDefault,\n __classPrivateFieldGet,\n __classPrivateFieldSet,\n __classPrivateFieldIn,\n __addDisposableResource,\n __disposeResources,\n};\n", "/**\n * Returns true if the object is a function.\n * @param value The value to check\n */\nexport function isFunction(value: any): value is (...args: any[]) => any {\n return typeof value === 'function';\n}\n", "/**\n * Used to create Error subclasses until the community moves away from ES5.\n *\n * This is because compiling from TypeScript down to ES5 has issues with subclassing Errors\n * as well as other built-in types: https://github.com/Microsoft/TypeScript/issues/12123\n *\n * @param createImpl A factory function to create the actual constructor implementation. The returned\n * function should be a named function that calls `_super` internally.\n */\nexport function createErrorClass(createImpl: (_super: any) => any): T {\n const _super = (instance: any) => {\n Error.call(instance);\n instance.stack = new Error().stack;\n };\n\n const ctorFunc = createImpl(_super);\n ctorFunc.prototype = Object.create(Error.prototype);\n ctorFunc.prototype.constructor = ctorFunc;\n return ctorFunc;\n}\n", "import { createErrorClass } from './createErrorClass';\n\nexport interface UnsubscriptionError extends Error {\n readonly errors: any[];\n}\n\nexport interface UnsubscriptionErrorCtor {\n /**\n * @deprecated Internal implementation detail. Do not construct error instances.\n * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n */\n new (errors: any[]): UnsubscriptionError;\n}\n\n/**\n * An error thrown when one or more errors have occurred during the\n * `unsubscribe` of a {@link Subscription}.\n */\nexport const UnsubscriptionError: UnsubscriptionErrorCtor = createErrorClass(\n (_super) =>\n function UnsubscriptionErrorImpl(this: any, errors: (Error | string)[]) {\n _super(this);\n this.message = errors\n ? `${errors.length} errors occurred during unsubscription:\n${errors.map((err, i) => `${i + 1}) ${err.toString()}`).join('\\n ')}`\n : '';\n this.name = 'UnsubscriptionError';\n this.errors = errors;\n }\n);\n", "/**\n * Removes an item from an array, mutating it.\n * @param arr The array to remove the item from\n * @param item The item to remove\n */\nexport function arrRemove(arr: T[] | undefined | null, item: T) {\n if (arr) {\n const index = arr.indexOf(item);\n 0 <= index && arr.splice(index, 1);\n }\n}\n", "import { isFunction } from './util/isFunction';\nimport { UnsubscriptionError } from './util/UnsubscriptionError';\nimport { SubscriptionLike, TeardownLogic, Unsubscribable } from './types';\nimport { arrRemove } from './util/arrRemove';\n\n/**\n * Represents a disposable resource, such as the execution of an Observable. A\n * Subscription has one important method, `unsubscribe`, that takes no argument\n * and just disposes the resource held by the subscription.\n *\n * Additionally, subscriptions may be grouped together through the `add()`\n * method, which will attach a child Subscription to the current Subscription.\n * When a Subscription is unsubscribed, all its children (and its grandchildren)\n * will be unsubscribed as well.\n *\n * @class Subscription\n */\nexport class Subscription implements SubscriptionLike {\n /** @nocollapse */\n public static EMPTY = (() => {\n const empty = new Subscription();\n empty.closed = true;\n return empty;\n })();\n\n /**\n * A flag to indicate whether this Subscription has already been unsubscribed.\n */\n public closed = false;\n\n private _parentage: Subscription[] | Subscription | null = null;\n\n /**\n * The list of registered finalizers to execute upon unsubscription. Adding and removing from this\n * list occurs in the {@link #add} and {@link #remove} methods.\n */\n private _finalizers: Exclude[] | null = null;\n\n /**\n * @param initialTeardown A function executed first as part of the finalization\n * process that is kicked off when {@link #unsubscribe} is called.\n */\n constructor(private initialTeardown?: () => void) {}\n\n /**\n * Disposes the resources held by the subscription. May, for instance, cancel\n * an ongoing Observable execution or cancel any other type of work that\n * started when the Subscription was created.\n * @return {void}\n */\n unsubscribe(): void {\n let errors: any[] | undefined;\n\n if (!this.closed) {\n this.closed = true;\n\n // Remove this from it's parents.\n const { _parentage } = this;\n if (_parentage) {\n this._parentage = null;\n if (Array.isArray(_parentage)) {\n for (const parent of _parentage) {\n parent.remove(this);\n }\n } else {\n _parentage.remove(this);\n }\n }\n\n const { initialTeardown: initialFinalizer } = this;\n if (isFunction(initialFinalizer)) {\n try {\n initialFinalizer();\n } catch (e) {\n errors = e instanceof UnsubscriptionError ? e.errors : [e];\n }\n }\n\n const { _finalizers } = this;\n if (_finalizers) {\n this._finalizers = null;\n for (const finalizer of _finalizers) {\n try {\n execFinalizer(finalizer);\n } catch (err) {\n errors = errors ?? [];\n if (err instanceof UnsubscriptionError) {\n errors = [...errors, ...err.errors];\n } else {\n errors.push(err);\n }\n }\n }\n }\n\n if (errors) {\n throw new UnsubscriptionError(errors);\n }\n }\n }\n\n /**\n * Adds a finalizer to this subscription, so that finalization will be unsubscribed/called\n * when this subscription is unsubscribed. If this subscription is already {@link #closed},\n * because it has already been unsubscribed, then whatever finalizer is passed to it\n * will automatically be executed (unless the finalizer itself is also a closed subscription).\n *\n * Closed Subscriptions cannot be added as finalizers to any subscription. Adding a closed\n * subscription to a any subscription will result in no operation. (A noop).\n *\n * Adding a subscription to itself, or adding `null` or `undefined` will not perform any\n * operation at all. (A noop).\n *\n * `Subscription` instances that are added to this instance will automatically remove themselves\n * if they are unsubscribed. Functions and {@link Unsubscribable} objects that you wish to remove\n * will need to be removed manually with {@link #remove}\n *\n * @param teardown The finalization logic to add to this subscription.\n */\n add(teardown: TeardownLogic): void {\n // Only add the finalizer if it's not undefined\n // and don't add a subscription to itself.\n if (teardown && teardown !== this) {\n if (this.closed) {\n // If this subscription is already closed,\n // execute whatever finalizer is handed to it automatically.\n execFinalizer(teardown);\n } else {\n if (teardown instanceof Subscription) {\n // We don't add closed subscriptions, and we don't add the same subscription\n // twice. Subscription unsubscribe is idempotent.\n if (teardown.closed || teardown._hasParent(this)) {\n return;\n }\n teardown._addParent(this);\n }\n (this._finalizers = this._finalizers ?? []).push(teardown);\n }\n }\n }\n\n /**\n * Checks to see if a this subscription already has a particular parent.\n * This will signal that this subscription has already been added to the parent in question.\n * @param parent the parent to check for\n */\n private _hasParent(parent: Subscription) {\n const { _parentage } = this;\n return _parentage === parent || (Array.isArray(_parentage) && _parentage.includes(parent));\n }\n\n /**\n * Adds a parent to this subscription so it can be removed from the parent if it\n * unsubscribes on it's own.\n *\n * NOTE: THIS ASSUMES THAT {@link _hasParent} HAS ALREADY BEEN CHECKED.\n * @param parent The parent subscription to add\n */\n private _addParent(parent: Subscription) {\n const { _parentage } = this;\n this._parentage = Array.isArray(_parentage) ? (_parentage.push(parent), _parentage) : _parentage ? [_parentage, parent] : parent;\n }\n\n /**\n * Called on a child when it is removed via {@link #remove}.\n * @param parent The parent to remove\n */\n private _removeParent(parent: Subscription) {\n const { _parentage } = this;\n if (_parentage === parent) {\n this._parentage = null;\n } else if (Array.isArray(_parentage)) {\n arrRemove(_parentage, parent);\n }\n }\n\n /**\n * Removes a finalizer from this subscription that was previously added with the {@link #add} method.\n *\n * Note that `Subscription` instances, when unsubscribed, will automatically remove themselves\n * from every other `Subscription` they have been added to. This means that using the `remove` method\n * is not a common thing and should be used thoughtfully.\n *\n * If you add the same finalizer instance of a function or an unsubscribable object to a `Subscription` instance\n * more than once, you will need to call `remove` the same number of times to remove all instances.\n *\n * All finalizer instances are removed to free up memory upon unsubscription.\n *\n * @param teardown The finalizer to remove from this subscription\n */\n remove(teardown: Exclude): void {\n const { _finalizers } = this;\n _finalizers && arrRemove(_finalizers, teardown);\n\n if (teardown instanceof Subscription) {\n teardown._removeParent(this);\n }\n }\n}\n\nexport const EMPTY_SUBSCRIPTION = Subscription.EMPTY;\n\nexport function isSubscription(value: any): value is Subscription {\n return (\n value instanceof Subscription ||\n (value && 'closed' in value && isFunction(value.remove) && isFunction(value.add) && isFunction(value.unsubscribe))\n );\n}\n\nfunction execFinalizer(finalizer: Unsubscribable | (() => void)) {\n if (isFunction(finalizer)) {\n finalizer();\n } else {\n finalizer.unsubscribe();\n }\n}\n", "import { Subscriber } from './Subscriber';\nimport { ObservableNotification } from './types';\n\n/**\n * The {@link GlobalConfig} object for RxJS. It is used to configure things\n * like how to react on unhandled errors.\n */\nexport const config: GlobalConfig = {\n onUnhandledError: null,\n onStoppedNotification: null,\n Promise: undefined,\n useDeprecatedSynchronousErrorHandling: false,\n useDeprecatedNextContext: false,\n};\n\n/**\n * The global configuration object for RxJS, used to configure things\n * like how to react on unhandled errors. Accessible via {@link config}\n * object.\n */\nexport interface GlobalConfig {\n /**\n * A registration point for unhandled errors from RxJS. These are errors that\n * cannot were not handled by consuming code in the usual subscription path. For\n * example, if you have this configured, and you subscribe to an observable without\n * providing an error handler, errors from that subscription will end up here. This\n * will _always_ be called asynchronously on another job in the runtime. This is because\n * we do not want errors thrown in this user-configured handler to interfere with the\n * behavior of the library.\n */\n onUnhandledError: ((err: any) => void) | null;\n\n /**\n * A registration point for notifications that cannot be sent to subscribers because they\n * have completed, errored or have been explicitly unsubscribed. By default, next, complete\n * and error notifications sent to stopped subscribers are noops. However, sometimes callers\n * might want a different behavior. For example, with sources that attempt to report errors\n * to stopped subscribers, a caller can configure RxJS to throw an unhandled error instead.\n * This will _always_ be called asynchronously on another job in the runtime. This is because\n * we do not want errors thrown in this user-configured handler to interfere with the\n * behavior of the library.\n */\n onStoppedNotification: ((notification: ObservableNotification, subscriber: Subscriber) => void) | null;\n\n /**\n * The promise constructor used by default for {@link Observable#toPromise toPromise} and {@link Observable#forEach forEach}\n * methods.\n *\n * @deprecated As of version 8, RxJS will no longer support this sort of injection of a\n * Promise constructor. If you need a Promise implementation other than native promises,\n * please polyfill/patch Promise as you see appropriate. Will be removed in v8.\n */\n Promise?: PromiseConstructorLike;\n\n /**\n * If true, turns on synchronous error rethrowing, which is a deprecated behavior\n * in v6 and higher. This behavior enables bad patterns like wrapping a subscribe\n * call in a try/catch block. It also enables producer interference, a nasty bug\n * where a multicast can be broken for all observers by a downstream consumer with\n * an unhandled error. DO NOT USE THIS FLAG UNLESS IT'S NEEDED TO BUY TIME\n * FOR MIGRATION REASONS.\n *\n * @deprecated As of version 8, RxJS will no longer support synchronous throwing\n * of unhandled errors. All errors will be thrown on a separate call stack to prevent bad\n * behaviors described above. Will be removed in v8.\n */\n useDeprecatedSynchronousErrorHandling: boolean;\n\n /**\n * If true, enables an as-of-yet undocumented feature from v5: The ability to access\n * `unsubscribe()` via `this` context in `next` functions created in observers passed\n * to `subscribe`.\n *\n * This is being removed because the performance was severely problematic, and it could also cause\n * issues when types other than POJOs are passed to subscribe as subscribers, as they will likely have\n * their `this` context overwritten.\n *\n * @deprecated As of version 8, RxJS will no longer support altering the\n * context of next functions provided as part of an observer to Subscribe. Instead,\n * you will have access to a subscription or a signal or token that will allow you to do things like\n * unsubscribe and test closed status. Will be removed in v8.\n */\n useDeprecatedNextContext: boolean;\n}\n", "import type { TimerHandle } from './timerHandle';\ntype SetTimeoutFunction = (handler: () => void, timeout?: number, ...args: any[]) => TimerHandle;\ntype ClearTimeoutFunction = (handle: TimerHandle) => void;\n\ninterface TimeoutProvider {\n setTimeout: SetTimeoutFunction;\n clearTimeout: ClearTimeoutFunction;\n delegate:\n | {\n setTimeout: SetTimeoutFunction;\n clearTimeout: ClearTimeoutFunction;\n }\n | undefined;\n}\n\nexport const timeoutProvider: TimeoutProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n setTimeout(handler: () => void, timeout?: number, ...args) {\n const { delegate } = timeoutProvider;\n if (delegate?.setTimeout) {\n return delegate.setTimeout(handler, timeout, ...args);\n }\n return setTimeout(handler, timeout, ...args);\n },\n clearTimeout(handle) {\n const { delegate } = timeoutProvider;\n return (delegate?.clearTimeout || clearTimeout)(handle as any);\n },\n delegate: undefined,\n};\n", "import { config } from '../config';\nimport { timeoutProvider } from '../scheduler/timeoutProvider';\n\n/**\n * Handles an error on another job either with the user-configured {@link onUnhandledError},\n * or by throwing it on that new job so it can be picked up by `window.onerror`, `process.on('error')`, etc.\n *\n * This should be called whenever there is an error that is out-of-band with the subscription\n * or when an error hits a terminal boundary of the subscription and no error handler was provided.\n *\n * @param err the error to report\n */\nexport function reportUnhandledError(err: any) {\n timeoutProvider.setTimeout(() => {\n const { onUnhandledError } = config;\n if (onUnhandledError) {\n // Execute the user-configured error handler.\n onUnhandledError(err);\n } else {\n // Throw so it is picked up by the runtime's uncaught error mechanism.\n throw err;\n }\n });\n}\n", "/* tslint:disable:no-empty */\nexport function noop() { }\n", "import { CompleteNotification, NextNotification, ErrorNotification } from './types';\n\n/**\n * A completion object optimized for memory use and created to be the\n * same \"shape\" as other notifications in v8.\n * @internal\n */\nexport const COMPLETE_NOTIFICATION = (() => createNotification('C', undefined, undefined) as CompleteNotification)();\n\n/**\n * Internal use only. Creates an optimized error notification that is the same \"shape\"\n * as other notifications.\n * @internal\n */\nexport function errorNotification(error: any): ErrorNotification {\n return createNotification('E', undefined, error) as any;\n}\n\n/**\n * Internal use only. Creates an optimized next notification that is the same \"shape\"\n * as other notifications.\n * @internal\n */\nexport function nextNotification(value: T) {\n return createNotification('N', value, undefined) as NextNotification;\n}\n\n/**\n * Ensures that all notifications created internally have the same \"shape\" in v8.\n *\n * TODO: This is only exported to support a crazy legacy test in `groupBy`.\n * @internal\n */\nexport function createNotification(kind: 'N' | 'E' | 'C', value: any, error: any) {\n return {\n kind,\n value,\n error,\n };\n}\n", "import { config } from '../config';\n\nlet context: { errorThrown: boolean; error: any } | null = null;\n\n/**\n * Handles dealing with errors for super-gross mode. Creates a context, in which\n * any synchronously thrown errors will be passed to {@link captureError}. Which\n * will record the error such that it will be rethrown after the call back is complete.\n * TODO: Remove in v8\n * @param cb An immediately executed function.\n */\nexport function errorContext(cb: () => void) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n const isRoot = !context;\n if (isRoot) {\n context = { errorThrown: false, error: null };\n }\n cb();\n if (isRoot) {\n const { errorThrown, error } = context!;\n context = null;\n if (errorThrown) {\n throw error;\n }\n }\n } else {\n // This is the general non-deprecated path for everyone that\n // isn't crazy enough to use super-gross mode (useDeprecatedSynchronousErrorHandling)\n cb();\n }\n}\n\n/**\n * Captures errors only in super-gross mode.\n * @param err the error to capture\n */\nexport function captureError(err: any) {\n if (config.useDeprecatedSynchronousErrorHandling && context) {\n context.errorThrown = true;\n context.error = err;\n }\n}\n", "import { isFunction } from './util/isFunction';\nimport { Observer, ObservableNotification } from './types';\nimport { isSubscription, Subscription } from './Subscription';\nimport { config } from './config';\nimport { reportUnhandledError } from './util/reportUnhandledError';\nimport { noop } from './util/noop';\nimport { nextNotification, errorNotification, COMPLETE_NOTIFICATION } from './NotificationFactories';\nimport { timeoutProvider } from './scheduler/timeoutProvider';\nimport { captureError } from './util/errorContext';\n\n/**\n * Implements the {@link Observer} interface and extends the\n * {@link Subscription} class. While the {@link Observer} is the public API for\n * consuming the values of an {@link Observable}, all Observers get converted to\n * a Subscriber, in order to provide Subscription-like capabilities such as\n * `unsubscribe`. Subscriber is a common type in RxJS, and crucial for\n * implementing operators, but it is rarely used as a public API.\n *\n * @class Subscriber\n */\nexport class Subscriber extends Subscription implements Observer {\n /**\n * A static factory for a Subscriber, given a (potentially partial) definition\n * of an Observer.\n * @param next The `next` callback of an Observer.\n * @param error The `error` callback of an\n * Observer.\n * @param complete The `complete` callback of an\n * Observer.\n * @return A Subscriber wrapping the (partially defined)\n * Observer represented by the given arguments.\n * @nocollapse\n * @deprecated Do not use. Will be removed in v8. There is no replacement for this\n * method, and there is no reason to be creating instances of `Subscriber` directly.\n * If you have a specific use case, please file an issue.\n */\n static create(next?: (x?: T) => void, error?: (e?: any) => void, complete?: () => void): Subscriber {\n return new SafeSubscriber(next, error, complete);\n }\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n protected isStopped: boolean = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n protected destination: Subscriber | Observer; // this `any` is the escape hatch to erase extra type param (e.g. R)\n\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n * There is no reason to directly create an instance of Subscriber. This type is exported for typings reasons.\n */\n constructor(destination?: Subscriber | Observer) {\n super();\n if (destination) {\n this.destination = destination;\n // Automatically chain subscriptions together here.\n // if destination is a Subscription, then it is a Subscriber.\n if (isSubscription(destination)) {\n destination.add(this);\n }\n } else {\n this.destination = EMPTY_OBSERVER;\n }\n }\n\n /**\n * The {@link Observer} callback to receive notifications of type `next` from\n * the Observable, with a value. The Observable may call this method 0 or more\n * times.\n * @param {T} [value] The `next` value.\n * @return {void}\n */\n next(value?: T): void {\n if (this.isStopped) {\n handleStoppedNotification(nextNotification(value), this);\n } else {\n this._next(value!);\n }\n }\n\n /**\n * The {@link Observer} callback to receive notifications of type `error` from\n * the Observable, with an attached `Error`. Notifies the Observer that\n * the Observable has experienced an error condition.\n * @param {any} [err] The `error` exception.\n * @return {void}\n */\n error(err?: any): void {\n if (this.isStopped) {\n handleStoppedNotification(errorNotification(err), this);\n } else {\n this.isStopped = true;\n this._error(err);\n }\n }\n\n /**\n * The {@link Observer} callback to receive a valueless notification of type\n * `complete` from the Observable. Notifies the Observer that the Observable\n * has finished sending push-based notifications.\n * @return {void}\n */\n complete(): void {\n if (this.isStopped) {\n handleStoppedNotification(COMPLETE_NOTIFICATION, this);\n } else {\n this.isStopped = true;\n this._complete();\n }\n }\n\n unsubscribe(): void {\n if (!this.closed) {\n this.isStopped = true;\n super.unsubscribe();\n this.destination = null!;\n }\n }\n\n protected _next(value: T): void {\n this.destination.next(value);\n }\n\n protected _error(err: any): void {\n try {\n this.destination.error(err);\n } finally {\n this.unsubscribe();\n }\n }\n\n protected _complete(): void {\n try {\n this.destination.complete();\n } finally {\n this.unsubscribe();\n }\n }\n}\n\n/**\n * This bind is captured here because we want to be able to have\n * compatibility with monoid libraries that tend to use a method named\n * `bind`. In particular, a library called Monio requires this.\n */\nconst _bind = Function.prototype.bind;\n\nfunction bind any>(fn: Fn, thisArg: any): Fn {\n return _bind.call(fn, thisArg);\n}\n\n/**\n * Internal optimization only, DO NOT EXPOSE.\n * @internal\n */\nclass ConsumerObserver implements Observer {\n constructor(private partialObserver: Partial>) {}\n\n next(value: T): void {\n const { partialObserver } = this;\n if (partialObserver.next) {\n try {\n partialObserver.next(value);\n } catch (error) {\n handleUnhandledError(error);\n }\n }\n }\n\n error(err: any): void {\n const { partialObserver } = this;\n if (partialObserver.error) {\n try {\n partialObserver.error(err);\n } catch (error) {\n handleUnhandledError(error);\n }\n } else {\n handleUnhandledError(err);\n }\n }\n\n complete(): void {\n const { partialObserver } = this;\n if (partialObserver.complete) {\n try {\n partialObserver.complete();\n } catch (error) {\n handleUnhandledError(error);\n }\n }\n }\n}\n\nexport class SafeSubscriber extends Subscriber {\n constructor(\n observerOrNext?: Partial> | ((value: T) => void) | null,\n error?: ((e?: any) => void) | null,\n complete?: (() => void) | null\n ) {\n super();\n\n let partialObserver: Partial>;\n if (isFunction(observerOrNext) || !observerOrNext) {\n // The first argument is a function, not an observer. The next\n // two arguments *could* be observers, or they could be empty.\n partialObserver = {\n next: (observerOrNext ?? undefined) as (((value: T) => void) | undefined),\n error: error ?? undefined,\n complete: complete ?? undefined,\n };\n } else {\n // The first argument is a partial observer.\n let context: any;\n if (this && config.useDeprecatedNextContext) {\n // This is a deprecated path that made `this.unsubscribe()` available in\n // next handler functions passed to subscribe. This only exists behind a flag\n // now, as it is *very* slow.\n context = Object.create(observerOrNext);\n context.unsubscribe = () => this.unsubscribe();\n partialObserver = {\n next: observerOrNext.next && bind(observerOrNext.next, context),\n error: observerOrNext.error && bind(observerOrNext.error, context),\n complete: observerOrNext.complete && bind(observerOrNext.complete, context),\n };\n } else {\n // The \"normal\" path. Just use the partial observer directly.\n partialObserver = observerOrNext;\n }\n }\n\n // Wrap the partial observer to ensure it's a full observer, and\n // make sure proper error handling is accounted for.\n this.destination = new ConsumerObserver(partialObserver);\n }\n}\n\nfunction handleUnhandledError(error: any) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n captureError(error);\n } else {\n // Ideal path, we report this as an unhandled error,\n // which is thrown on a new call stack.\n reportUnhandledError(error);\n }\n}\n\n/**\n * An error handler used when no error handler was supplied\n * to the SafeSubscriber -- meaning no error handler was supplied\n * do the `subscribe` call on our observable.\n * @param err The error to handle\n */\nfunction defaultErrorHandler(err: any) {\n throw err;\n}\n\n/**\n * A handler for notifications that cannot be sent to a stopped subscriber.\n * @param notification The notification being sent\n * @param subscriber The stopped subscriber\n */\nfunction handleStoppedNotification(notification: ObservableNotification, subscriber: Subscriber) {\n const { onStoppedNotification } = config;\n onStoppedNotification && timeoutProvider.setTimeout(() => onStoppedNotification(notification, subscriber));\n}\n\n/**\n * The observer used as a stub for subscriptions where the user did not\n * pass any arguments to `subscribe`. Comes with the default error handling\n * behavior.\n */\nexport const EMPTY_OBSERVER: Readonly> & { closed: true } = {\n closed: true,\n next: noop,\n error: defaultErrorHandler,\n complete: noop,\n};\n", "/**\n * Symbol.observable or a string \"@@observable\". Used for interop\n *\n * @deprecated We will no longer be exporting this symbol in upcoming versions of RxJS.\n * Instead polyfill and use Symbol.observable directly *or* use https://www.npmjs.com/package/symbol-observable\n */\nexport const observable: string | symbol = (() => (typeof Symbol === 'function' && Symbol.observable) || '@@observable')();\n", "/**\n * This function takes one parameter and just returns it. Simply put,\n * this is like `(x: T): T => x`.\n *\n * ## Examples\n *\n * This is useful in some cases when using things like `mergeMap`\n *\n * ```ts\n * import { interval, take, map, range, mergeMap, identity } from 'rxjs';\n *\n * const source$ = interval(1000).pipe(take(5));\n *\n * const result$ = source$.pipe(\n * map(i => range(i)),\n * mergeMap(identity) // same as mergeMap(x => x)\n * );\n *\n * result$.subscribe({\n * next: console.log\n * });\n * ```\n *\n * Or when you want to selectively apply an operator\n *\n * ```ts\n * import { interval, take, identity } from 'rxjs';\n *\n * const shouldLimit = () => Math.random() < 0.5;\n *\n * const source$ = interval(1000);\n *\n * const result$ = source$.pipe(shouldLimit() ? take(5) : identity);\n *\n * result$.subscribe({\n * next: console.log\n * });\n * ```\n *\n * @param x Any value that is returned by this function\n * @returns The value passed as the first parameter to this function\n */\nexport function identity(x: T): T {\n return x;\n}\n", "import { identity } from './identity';\nimport { UnaryFunction } from '../types';\n\nexport function pipe(): typeof identity;\nexport function pipe(fn1: UnaryFunction): UnaryFunction;\nexport function pipe(fn1: UnaryFunction, fn2: UnaryFunction): UnaryFunction;\nexport function pipe(fn1: UnaryFunction, fn2: UnaryFunction, fn3: UnaryFunction): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction,\n fn8: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction,\n fn8: UnaryFunction,\n fn9: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction,\n fn8: UnaryFunction,\n fn9: UnaryFunction,\n ...fns: UnaryFunction[]\n): UnaryFunction;\n\n/**\n * pipe() can be called on one or more functions, each of which can take one argument (\"UnaryFunction\")\n * and uses it to return a value.\n * It returns a function that takes one argument, passes it to the first UnaryFunction, and then\n * passes the result to the next one, passes that result to the next one, and so on. \n */\nexport function pipe(...fns: Array>): UnaryFunction {\n return pipeFromArray(fns);\n}\n\n/** @internal */\nexport function pipeFromArray(fns: Array>): UnaryFunction {\n if (fns.length === 0) {\n return identity as UnaryFunction;\n }\n\n if (fns.length === 1) {\n return fns[0];\n }\n\n return function piped(input: T): R {\n return fns.reduce((prev: any, fn: UnaryFunction) => fn(prev), input as any);\n };\n}\n", "import { Operator } from './Operator';\nimport { SafeSubscriber, Subscriber } from './Subscriber';\nimport { isSubscription, Subscription } from './Subscription';\nimport { TeardownLogic, OperatorFunction, Subscribable, Observer } from './types';\nimport { observable as Symbol_observable } from './symbol/observable';\nimport { pipeFromArray } from './util/pipe';\nimport { config } from './config';\nimport { isFunction } from './util/isFunction';\nimport { errorContext } from './util/errorContext';\n\n/**\n * A representation of any set of values over any amount of time. This is the most basic building block\n * of RxJS.\n *\n * @class Observable\n */\nexport class Observable implements Subscribable {\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n */\n source: Observable | undefined;\n\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n */\n operator: Operator | undefined;\n\n /**\n * @constructor\n * @param {Function} subscribe the function that is called when the Observable is\n * initially subscribed to. This function is given a Subscriber, to which new values\n * can be `next`ed, or an `error` method can be called to raise an error, or\n * `complete` can be called to notify of a successful completion.\n */\n constructor(subscribe?: (this: Observable, subscriber: Subscriber) => TeardownLogic) {\n if (subscribe) {\n this._subscribe = subscribe;\n }\n }\n\n // HACK: Since TypeScript inherits static properties too, we have to\n // fight against TypeScript here so Subject can have a different static create signature\n /**\n * Creates a new Observable by calling the Observable constructor\n * @owner Observable\n * @method create\n * @param {Function} subscribe? the subscriber function to be passed to the Observable constructor\n * @return {Observable} a new observable\n * @nocollapse\n * @deprecated Use `new Observable()` instead. Will be removed in v8.\n */\n static create: (...args: any[]) => any = (subscribe?: (subscriber: Subscriber) => TeardownLogic) => {\n return new Observable(subscribe);\n };\n\n /**\n * Creates a new Observable, with this Observable instance as the source, and the passed\n * operator defined as the new observable's operator.\n * @method lift\n * @param operator the operator defining the operation to take on the observable\n * @return a new observable with the Operator applied\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n * If you have implemented an operator using `lift`, it is recommended that you create an\n * operator by simply returning `new Observable()` directly. See \"Creating new operators from\n * scratch\" section here: https://rxjs.dev/guide/operators\n */\n lift(operator?: Operator): Observable {\n const observable = new Observable();\n observable.source = this;\n observable.operator = operator;\n return observable;\n }\n\n subscribe(observerOrNext?: Partial> | ((value: T) => void)): Subscription;\n /** @deprecated Instead of passing separate callback arguments, use an observer argument. Signatures taking separate callback arguments will be removed in v8. Details: https://rxjs.dev/deprecations/subscribe-arguments */\n subscribe(next?: ((value: T) => void) | null, error?: ((error: any) => void) | null, complete?: (() => void) | null): Subscription;\n /**\n * Invokes an execution of an Observable and registers Observer handlers for notifications it will emit.\n *\n * Use it when you have all these Observables, but still nothing is happening.\n *\n * `subscribe` is not a regular operator, but a method that calls Observable's internal `subscribe` function. It\n * might be for example a function that you passed to Observable's constructor, but most of the time it is\n * a library implementation, which defines what will be emitted by an Observable, and when it be will emitted. This means\n * that calling `subscribe` is actually the moment when Observable starts its work, not when it is created, as it is often\n * the thought.\n *\n * Apart from starting the execution of an Observable, this method allows you to listen for values\n * that an Observable emits, as well as for when it completes or errors. You can achieve this in two\n * of the following ways.\n *\n * The first way is creating an object that implements {@link Observer} interface. It should have methods\n * defined by that interface, but note that it should be just a regular JavaScript object, which you can create\n * yourself in any way you want (ES6 class, classic function constructor, object literal etc.). In particular, do\n * not attempt to use any RxJS implementation details to create Observers - you don't need them. Remember also\n * that your object does not have to implement all methods. If you find yourself creating a method that doesn't\n * do anything, you can simply omit it. Note however, if the `error` method is not provided and an error happens,\n * it will be thrown asynchronously. Errors thrown asynchronously cannot be caught using `try`/`catch`. Instead,\n * use the {@link onUnhandledError} configuration option or use a runtime handler (like `window.onerror` or\n * `process.on('error)`) to be notified of unhandled errors. Because of this, it's recommended that you provide\n * an `error` method to avoid missing thrown errors.\n *\n * The second way is to give up on Observer object altogether and simply provide callback functions in place of its methods.\n * This means you can provide three functions as arguments to `subscribe`, where the first function is equivalent\n * of a `next` method, the second of an `error` method and the third of a `complete` method. Just as in case of an Observer,\n * if you do not need to listen for something, you can omit a function by passing `undefined` or `null`,\n * since `subscribe` recognizes these functions by where they were placed in function call. When it comes\n * to the `error` function, as with an Observer, if not provided, errors emitted by an Observable will be thrown asynchronously.\n *\n * You can, however, subscribe with no parameters at all. This may be the case where you're not interested in terminal events\n * and you also handled emissions internally by using operators (e.g. using `tap`).\n *\n * Whichever style of calling `subscribe` you use, in both cases it returns a Subscription object.\n * This object allows you to call `unsubscribe` on it, which in turn will stop the work that an Observable does and will clean\n * up all resources that an Observable used. Note that cancelling a subscription will not call `complete` callback\n * provided to `subscribe` function, which is reserved for a regular completion signal that comes from an Observable.\n *\n * Remember that callbacks provided to `subscribe` are not guaranteed to be called asynchronously.\n * It is an Observable itself that decides when these functions will be called. For example {@link of}\n * by default emits all its values synchronously. Always check documentation for how given Observable\n * will behave when subscribed and if its default behavior can be modified with a `scheduler`.\n *\n * #### Examples\n *\n * Subscribe with an {@link guide/observer Observer}\n *\n * ```ts\n * import { of } from 'rxjs';\n *\n * const sumObserver = {\n * sum: 0,\n * next(value) {\n * console.log('Adding: ' + value);\n * this.sum = this.sum + value;\n * },\n * error() {\n * // We actually could just remove this method,\n * // since we do not really care about errors right now.\n * },\n * complete() {\n * console.log('Sum equals: ' + this.sum);\n * }\n * };\n *\n * of(1, 2, 3) // Synchronously emits 1, 2, 3 and then completes.\n * .subscribe(sumObserver);\n *\n * // Logs:\n * // 'Adding: 1'\n * // 'Adding: 2'\n * // 'Adding: 3'\n * // 'Sum equals: 6'\n * ```\n *\n * Subscribe with functions ({@link deprecations/subscribe-arguments deprecated})\n *\n * ```ts\n * import { of } from 'rxjs'\n *\n * let sum = 0;\n *\n * of(1, 2, 3).subscribe(\n * value => {\n * console.log('Adding: ' + value);\n * sum = sum + value;\n * },\n * undefined,\n * () => console.log('Sum equals: ' + sum)\n * );\n *\n * // Logs:\n * // 'Adding: 1'\n * // 'Adding: 2'\n * // 'Adding: 3'\n * // 'Sum equals: 6'\n * ```\n *\n * Cancel a subscription\n *\n * ```ts\n * import { interval } from 'rxjs';\n *\n * const subscription = interval(1000).subscribe({\n * next(num) {\n * console.log(num)\n * },\n * complete() {\n * // Will not be called, even when cancelling subscription.\n * console.log('completed!');\n * }\n * });\n *\n * setTimeout(() => {\n * subscription.unsubscribe();\n * console.log('unsubscribed!');\n * }, 2500);\n *\n * // Logs:\n * // 0 after 1s\n * // 1 after 2s\n * // 'unsubscribed!' after 2.5s\n * ```\n *\n * @param {Observer|Function} observerOrNext (optional) Either an observer with methods to be called,\n * or the first of three possible handlers, which is the handler for each value emitted from the subscribed\n * Observable.\n * @param {Function} error (optional) A handler for a terminal event resulting from an error. If no error handler is provided,\n * the error will be thrown asynchronously as unhandled.\n * @param {Function} complete (optional) A handler for a terminal event resulting from successful completion.\n * @return {Subscription} a subscription reference to the registered handlers\n * @method subscribe\n */\n subscribe(\n observerOrNext?: Partial> | ((value: T) => void) | null,\n error?: ((error: any) => void) | null,\n complete?: (() => void) | null\n ): Subscription {\n const subscriber = isSubscriber(observerOrNext) ? observerOrNext : new SafeSubscriber(observerOrNext, error, complete);\n\n errorContext(() => {\n const { operator, source } = this;\n subscriber.add(\n operator\n ? // We're dealing with a subscription in the\n // operator chain to one of our lifted operators.\n operator.call(subscriber, source)\n : source\n ? // If `source` has a value, but `operator` does not, something that\n // had intimate knowledge of our API, like our `Subject`, must have\n // set it. We're going to just call `_subscribe` directly.\n this._subscribe(subscriber)\n : // In all other cases, we're likely wrapping a user-provided initializer\n // function, so we need to catch errors and handle them appropriately.\n this._trySubscribe(subscriber)\n );\n });\n\n return subscriber;\n }\n\n /** @internal */\n protected _trySubscribe(sink: Subscriber): TeardownLogic {\n try {\n return this._subscribe(sink);\n } catch (err) {\n // We don't need to return anything in this case,\n // because it's just going to try to `add()` to a subscription\n // above.\n sink.error(err);\n }\n }\n\n /**\n * Used as a NON-CANCELLABLE means of subscribing to an observable, for use with\n * APIs that expect promises, like `async/await`. You cannot unsubscribe from this.\n *\n * **WARNING**: Only use this with observables you *know* will complete. If the source\n * observable does not complete, you will end up with a promise that is hung up, and\n * potentially all of the state of an async function hanging out in memory. To avoid\n * this situation, look into adding something like {@link timeout}, {@link take},\n * {@link takeWhile}, or {@link takeUntil} amongst others.\n *\n * #### Example\n *\n * ```ts\n * import { interval, take } from 'rxjs';\n *\n * const source$ = interval(1000).pipe(take(4));\n *\n * async function getTotal() {\n * let total = 0;\n *\n * await source$.forEach(value => {\n * total += value;\n * console.log('observable -> ' + value);\n * });\n *\n * return total;\n * }\n *\n * getTotal().then(\n * total => console.log('Total: ' + total)\n * );\n *\n * // Expected:\n * // 'observable -> 0'\n * // 'observable -> 1'\n * // 'observable -> 2'\n * // 'observable -> 3'\n * // 'Total: 6'\n * ```\n *\n * @param next a handler for each value emitted by the observable\n * @return a promise that either resolves on observable completion or\n * rejects with the handled error\n */\n forEach(next: (value: T) => void): Promise;\n\n /**\n * @param next a handler for each value emitted by the observable\n * @param promiseCtor a constructor function used to instantiate the Promise\n * @return a promise that either resolves on observable completion or\n * rejects with the handled error\n * @deprecated Passing a Promise constructor will no longer be available\n * in upcoming versions of RxJS. This is because it adds weight to the library, for very\n * little benefit. If you need this functionality, it is recommended that you either\n * polyfill Promise, or you create an adapter to convert the returned native promise\n * to whatever promise implementation you wanted. Will be removed in v8.\n */\n forEach(next: (value: T) => void, promiseCtor: PromiseConstructorLike): Promise;\n\n forEach(next: (value: T) => void, promiseCtor?: PromiseConstructorLike): Promise {\n promiseCtor = getPromiseCtor(promiseCtor);\n\n return new promiseCtor((resolve, reject) => {\n const subscriber = new SafeSubscriber({\n next: (value) => {\n try {\n next(value);\n } catch (err) {\n reject(err);\n subscriber.unsubscribe();\n }\n },\n error: reject,\n complete: resolve,\n });\n this.subscribe(subscriber);\n }) as Promise;\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): TeardownLogic {\n return this.source?.subscribe(subscriber);\n }\n\n /**\n * An interop point defined by the es7-observable spec https://github.com/zenparsing/es-observable\n * @method Symbol.observable\n * @return {Observable} this instance of the observable\n */\n [Symbol_observable]() {\n return this;\n }\n\n /* tslint:disable:max-line-length */\n pipe(): Observable;\n pipe(op1: OperatorFunction): Observable;\n pipe(op1: OperatorFunction, op2: OperatorFunction): Observable;\n pipe(op1: OperatorFunction, op2: OperatorFunction, op3: OperatorFunction): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction,\n op8: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction,\n op8: OperatorFunction,\n op9: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction,\n op8: OperatorFunction,\n op9: OperatorFunction,\n ...operations: OperatorFunction[]\n ): Observable;\n /* tslint:enable:max-line-length */\n\n /**\n * Used to stitch together functional operators into a chain.\n * @method pipe\n * @return {Observable} the Observable result of all of the operators having\n * been called in the order they were passed in.\n *\n * ## Example\n *\n * ```ts\n * import { interval, filter, map, scan } from 'rxjs';\n *\n * interval(1000)\n * .pipe(\n * filter(x => x % 2 === 0),\n * map(x => x + x),\n * scan((acc, x) => acc + x)\n * )\n * .subscribe(x => console.log(x));\n * ```\n */\n pipe(...operations: OperatorFunction[]): Observable {\n return pipeFromArray(operations)(this);\n }\n\n /* tslint:disable:max-line-length */\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(): Promise;\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(PromiseCtor: typeof Promise): Promise;\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(PromiseCtor: PromiseConstructorLike): Promise;\n /* tslint:enable:max-line-length */\n\n /**\n * Subscribe to this Observable and get a Promise resolving on\n * `complete` with the last emission (if any).\n *\n * **WARNING**: Only use this with observables you *know* will complete. If the source\n * observable does not complete, you will end up with a promise that is hung up, and\n * potentially all of the state of an async function hanging out in memory. To avoid\n * this situation, look into adding something like {@link timeout}, {@link take},\n * {@link takeWhile}, or {@link takeUntil} amongst others.\n *\n * @method toPromise\n * @param [promiseCtor] a constructor function used to instantiate\n * the Promise\n * @return A Promise that resolves with the last value emit, or\n * rejects on an error. If there were no emissions, Promise\n * resolves with undefined.\n * @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise\n */\n toPromise(promiseCtor?: PromiseConstructorLike): Promise {\n promiseCtor = getPromiseCtor(promiseCtor);\n\n return new promiseCtor((resolve, reject) => {\n let value: T | undefined;\n this.subscribe(\n (x: T) => (value = x),\n (err: any) => reject(err),\n () => resolve(value)\n );\n }) as Promise;\n }\n}\n\n/**\n * Decides between a passed promise constructor from consuming code,\n * A default configured promise constructor, and the native promise\n * constructor and returns it. If nothing can be found, it will throw\n * an error.\n * @param promiseCtor The optional promise constructor to passed by consuming code\n */\nfunction getPromiseCtor(promiseCtor: PromiseConstructorLike | undefined) {\n return promiseCtor ?? config.Promise ?? Promise;\n}\n\nfunction isObserver(value: any): value is Observer {\n return value && isFunction(value.next) && isFunction(value.error) && isFunction(value.complete);\n}\n\nfunction isSubscriber(value: any): value is Subscriber {\n return (value && value instanceof Subscriber) || (isObserver(value) && isSubscription(value));\n}\n", "import { Observable } from '../Observable';\nimport { Subscriber } from '../Subscriber';\nimport { OperatorFunction } from '../types';\nimport { isFunction } from './isFunction';\n\n/**\n * Used to determine if an object is an Observable with a lift function.\n */\nexport function hasLift(source: any): source is { lift: InstanceType['lift'] } {\n return isFunction(source?.lift);\n}\n\n/**\n * Creates an `OperatorFunction`. Used to define operators throughout the library in a concise way.\n * @param init The logic to connect the liftedSource to the subscriber at the moment of subscription.\n */\nexport function operate(\n init: (liftedSource: Observable, subscriber: Subscriber) => (() => void) | void\n): OperatorFunction {\n return (source: Observable) => {\n if (hasLift(source)) {\n return source.lift(function (this: Subscriber, liftedSource: Observable) {\n try {\n return init(liftedSource, this);\n } catch (err) {\n this.error(err);\n }\n });\n }\n throw new TypeError('Unable to lift unknown Observable type');\n };\n}\n", "import { Subscriber } from '../Subscriber';\n\n/**\n * Creates an instance of an `OperatorSubscriber`.\n * @param destination The downstream subscriber.\n * @param onNext Handles next values, only called if this subscriber is not stopped or closed. Any\n * error that occurs in this function is caught and sent to the `error` method of this subscriber.\n * @param onError Handles errors from the subscription, any errors that occur in this handler are caught\n * and send to the `destination` error handler.\n * @param onComplete Handles completion notification from the subscription. Any errors that occur in\n * this handler are sent to the `destination` error handler.\n * @param onFinalize Additional teardown logic here. This will only be called on teardown if the\n * subscriber itself is not already closed. This is called after all other teardown logic is executed.\n */\nexport function createOperatorSubscriber(\n destination: Subscriber,\n onNext?: (value: T) => void,\n onComplete?: () => void,\n onError?: (err: any) => void,\n onFinalize?: () => void\n): Subscriber {\n return new OperatorSubscriber(destination, onNext, onComplete, onError, onFinalize);\n}\n\n/**\n * A generic helper for allowing operators to be created with a Subscriber and\n * use closures to capture necessary state from the operator function itself.\n */\nexport class OperatorSubscriber extends Subscriber {\n /**\n * Creates an instance of an `OperatorSubscriber`.\n * @param destination The downstream subscriber.\n * @param onNext Handles next values, only called if this subscriber is not stopped or closed. Any\n * error that occurs in this function is caught and sent to the `error` method of this subscriber.\n * @param onError Handles errors from the subscription, any errors that occur in this handler are caught\n * and send to the `destination` error handler.\n * @param onComplete Handles completion notification from the subscription. Any errors that occur in\n * this handler are sent to the `destination` error handler.\n * @param onFinalize Additional finalization logic here. This will only be called on finalization if the\n * subscriber itself is not already closed. This is called after all other finalization logic is executed.\n * @param shouldUnsubscribe An optional check to see if an unsubscribe call should truly unsubscribe.\n * NOTE: This currently **ONLY** exists to support the strange behavior of {@link groupBy}, where unsubscription\n * to the resulting observable does not actually disconnect from the source if there are active subscriptions\n * to any grouped observable. (DO NOT EXPOSE OR USE EXTERNALLY!!!)\n */\n constructor(\n destination: Subscriber,\n onNext?: (value: T) => void,\n onComplete?: () => void,\n onError?: (err: any) => void,\n private onFinalize?: () => void,\n private shouldUnsubscribe?: () => boolean\n ) {\n // It's important - for performance reasons - that all of this class's\n // members are initialized and that they are always initialized in the same\n // order. This will ensure that all OperatorSubscriber instances have the\n // same hidden class in V8. This, in turn, will help keep the number of\n // hidden classes involved in property accesses within the base class as\n // low as possible. If the number of hidden classes involved exceeds four,\n // the property accesses will become megamorphic and performance penalties\n // will be incurred - i.e. inline caches won't be used.\n //\n // The reasons for ensuring all instances have the same hidden class are\n // further discussed in this blog post from Benedikt Meurer:\n // https://benediktmeurer.de/2018/03/23/impact-of-polymorphism-on-component-based-frameworks-like-react/\n super(destination);\n this._next = onNext\n ? function (this: OperatorSubscriber, value: T) {\n try {\n onNext(value);\n } catch (err) {\n destination.error(err);\n }\n }\n : super._next;\n this._error = onError\n ? function (this: OperatorSubscriber, err: any) {\n try {\n onError(err);\n } catch (err) {\n // Send any errors that occur down stream.\n destination.error(err);\n } finally {\n // Ensure finalization.\n this.unsubscribe();\n }\n }\n : super._error;\n this._complete = onComplete\n ? function (this: OperatorSubscriber) {\n try {\n onComplete();\n } catch (err) {\n // Send any errors that occur down stream.\n destination.error(err);\n } finally {\n // Ensure finalization.\n this.unsubscribe();\n }\n }\n : super._complete;\n }\n\n unsubscribe() {\n if (!this.shouldUnsubscribe || this.shouldUnsubscribe()) {\n const { closed } = this;\n super.unsubscribe();\n // Execute additional teardown if we have any and we didn't already do so.\n !closed && this.onFinalize?.();\n }\n }\n}\n", "import { Subscription } from '../Subscription';\n\ninterface AnimationFrameProvider {\n schedule(callback: FrameRequestCallback): Subscription;\n requestAnimationFrame: typeof requestAnimationFrame;\n cancelAnimationFrame: typeof cancelAnimationFrame;\n delegate:\n | {\n requestAnimationFrame: typeof requestAnimationFrame;\n cancelAnimationFrame: typeof cancelAnimationFrame;\n }\n | undefined;\n}\n\nexport const animationFrameProvider: AnimationFrameProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n schedule(callback) {\n let request = requestAnimationFrame;\n let cancel: typeof cancelAnimationFrame | undefined = cancelAnimationFrame;\n const { delegate } = animationFrameProvider;\n if (delegate) {\n request = delegate.requestAnimationFrame;\n cancel = delegate.cancelAnimationFrame;\n }\n const handle = request((timestamp) => {\n // Clear the cancel function. The request has been fulfilled, so\n // attempting to cancel the request upon unsubscription would be\n // pointless.\n cancel = undefined;\n callback(timestamp);\n });\n return new Subscription(() => cancel?.(handle));\n },\n requestAnimationFrame(...args) {\n const { delegate } = animationFrameProvider;\n return (delegate?.requestAnimationFrame || requestAnimationFrame)(...args);\n },\n cancelAnimationFrame(...args) {\n const { delegate } = animationFrameProvider;\n return (delegate?.cancelAnimationFrame || cancelAnimationFrame)(...args);\n },\n delegate: undefined,\n};\n", "import { createErrorClass } from './createErrorClass';\n\nexport interface ObjectUnsubscribedError extends Error {}\n\nexport interface ObjectUnsubscribedErrorCtor {\n /**\n * @deprecated Internal implementation detail. Do not construct error instances.\n * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n */\n new (): ObjectUnsubscribedError;\n}\n\n/**\n * An error thrown when an action is invalid because the object has been\n * unsubscribed.\n *\n * @see {@link Subject}\n * @see {@link BehaviorSubject}\n *\n * @class ObjectUnsubscribedError\n */\nexport const ObjectUnsubscribedError: ObjectUnsubscribedErrorCtor = createErrorClass(\n (_super) =>\n function ObjectUnsubscribedErrorImpl(this: any) {\n _super(this);\n this.name = 'ObjectUnsubscribedError';\n this.message = 'object unsubscribed';\n }\n);\n", "import { Operator } from './Operator';\nimport { Observable } from './Observable';\nimport { Subscriber } from './Subscriber';\nimport { Subscription, EMPTY_SUBSCRIPTION } from './Subscription';\nimport { Observer, SubscriptionLike, TeardownLogic } from './types';\nimport { ObjectUnsubscribedError } from './util/ObjectUnsubscribedError';\nimport { arrRemove } from './util/arrRemove';\nimport { errorContext } from './util/errorContext';\n\n/**\n * A Subject is a special type of Observable that allows values to be\n * multicasted to many Observers. Subjects are like EventEmitters.\n *\n * Every Subject is an Observable and an Observer. You can subscribe to a\n * Subject, and you can call next to feed values as well as error and complete.\n */\nexport class Subject extends Observable implements SubscriptionLike {\n closed = false;\n\n private currentObservers: Observer[] | null = null;\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n observers: Observer[] = [];\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n isStopped = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n hasError = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n thrownError: any = null;\n\n /**\n * Creates a \"subject\" by basically gluing an observer to an observable.\n *\n * @nocollapse\n * @deprecated Recommended you do not use. Will be removed at some point in the future. Plans for replacement still under discussion.\n */\n static create: (...args: any[]) => any = (destination: Observer, source: Observable): AnonymousSubject => {\n return new AnonymousSubject(destination, source);\n };\n\n constructor() {\n // NOTE: This must be here to obscure Observable's constructor.\n super();\n }\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n lift(operator: Operator): Observable {\n const subject = new AnonymousSubject(this, this);\n subject.operator = operator as any;\n return subject as any;\n }\n\n /** @internal */\n protected _throwIfClosed() {\n if (this.closed) {\n throw new ObjectUnsubscribedError();\n }\n }\n\n next(value: T) {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n if (!this.currentObservers) {\n this.currentObservers = Array.from(this.observers);\n }\n for (const observer of this.currentObservers) {\n observer.next(value);\n }\n }\n });\n }\n\n error(err: any) {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n this.hasError = this.isStopped = true;\n this.thrownError = err;\n const { observers } = this;\n while (observers.length) {\n observers.shift()!.error(err);\n }\n }\n });\n }\n\n complete() {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n this.isStopped = true;\n const { observers } = this;\n while (observers.length) {\n observers.shift()!.complete();\n }\n }\n });\n }\n\n unsubscribe() {\n this.isStopped = this.closed = true;\n this.observers = this.currentObservers = null!;\n }\n\n get observed() {\n return this.observers?.length > 0;\n }\n\n /** @internal */\n protected _trySubscribe(subscriber: Subscriber): TeardownLogic {\n this._throwIfClosed();\n return super._trySubscribe(subscriber);\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n this._throwIfClosed();\n this._checkFinalizedStatuses(subscriber);\n return this._innerSubscribe(subscriber);\n }\n\n /** @internal */\n protected _innerSubscribe(subscriber: Subscriber) {\n const { hasError, isStopped, observers } = this;\n if (hasError || isStopped) {\n return EMPTY_SUBSCRIPTION;\n }\n this.currentObservers = null;\n observers.push(subscriber);\n return new Subscription(() => {\n this.currentObservers = null;\n arrRemove(observers, subscriber);\n });\n }\n\n /** @internal */\n protected _checkFinalizedStatuses(subscriber: Subscriber) {\n const { hasError, thrownError, isStopped } = this;\n if (hasError) {\n subscriber.error(thrownError);\n } else if (isStopped) {\n subscriber.complete();\n }\n }\n\n /**\n * Creates a new Observable with this Subject as the source. You can do this\n * to create custom Observer-side logic of the Subject and conceal it from\n * code that uses the Observable.\n * @return {Observable} Observable that the Subject casts to\n */\n asObservable(): Observable {\n const observable: any = new Observable();\n observable.source = this;\n return observable;\n }\n}\n\n/**\n * @class AnonymousSubject\n */\nexport class AnonymousSubject extends Subject {\n constructor(\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n public destination?: Observer,\n source?: Observable\n ) {\n super();\n this.source = source;\n }\n\n next(value: T) {\n this.destination?.next?.(value);\n }\n\n error(err: any) {\n this.destination?.error?.(err);\n }\n\n complete() {\n this.destination?.complete?.();\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n return this.source?.subscribe(subscriber) ?? EMPTY_SUBSCRIPTION;\n }\n}\n", "import { Subject } from './Subject';\nimport { Subscriber } from './Subscriber';\nimport { Subscription } from './Subscription';\n\n/**\n * A variant of Subject that requires an initial value and emits its current\n * value whenever it is subscribed to.\n *\n * @class BehaviorSubject\n */\nexport class BehaviorSubject extends Subject {\n constructor(private _value: T) {\n super();\n }\n\n get value(): T {\n return this.getValue();\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n const subscription = super._subscribe(subscriber);\n !subscription.closed && subscriber.next(this._value);\n return subscription;\n }\n\n getValue(): T {\n const { hasError, thrownError, _value } = this;\n if (hasError) {\n throw thrownError;\n }\n this._throwIfClosed();\n return _value;\n }\n\n next(value: T): void {\n super.next((this._value = value));\n }\n}\n", "import { TimestampProvider } from '../types';\n\ninterface DateTimestampProvider extends TimestampProvider {\n delegate: TimestampProvider | undefined;\n}\n\nexport const dateTimestampProvider: DateTimestampProvider = {\n now() {\n // Use the variable rather than `this` so that the function can be called\n // without being bound to the provider.\n return (dateTimestampProvider.delegate || Date).now();\n },\n delegate: undefined,\n};\n", "import { Subject } from './Subject';\nimport { TimestampProvider } from './types';\nimport { Subscriber } from './Subscriber';\nimport { Subscription } from './Subscription';\nimport { dateTimestampProvider } from './scheduler/dateTimestampProvider';\n\n/**\n * A variant of {@link Subject} that \"replays\" old values to new subscribers by emitting them when they first subscribe.\n *\n * `ReplaySubject` has an internal buffer that will store a specified number of values that it has observed. Like `Subject`,\n * `ReplaySubject` \"observes\" values by having them passed to its `next` method. When it observes a value, it will store that\n * value for a time determined by the configuration of the `ReplaySubject`, as passed to its constructor.\n *\n * When a new subscriber subscribes to the `ReplaySubject` instance, it will synchronously emit all values in its buffer in\n * a First-In-First-Out (FIFO) manner. The `ReplaySubject` will also complete, if it has observed completion; and it will\n * error if it has observed an error.\n *\n * There are two main configuration items to be concerned with:\n *\n * 1. `bufferSize` - This will determine how many items are stored in the buffer, defaults to infinite.\n * 2. `windowTime` - The amount of time to hold a value in the buffer before removing it from the buffer.\n *\n * Both configurations may exist simultaneously. So if you would like to buffer a maximum of 3 values, as long as the values\n * are less than 2 seconds old, you could do so with a `new ReplaySubject(3, 2000)`.\n *\n * ### Differences with BehaviorSubject\n *\n * `BehaviorSubject` is similar to `new ReplaySubject(1)`, with a couple of exceptions:\n *\n * 1. `BehaviorSubject` comes \"primed\" with a single value upon construction.\n * 2. `ReplaySubject` will replay values, even after observing an error, where `BehaviorSubject` will not.\n *\n * @see {@link Subject}\n * @see {@link BehaviorSubject}\n * @see {@link shareReplay}\n */\nexport class ReplaySubject extends Subject {\n private _buffer: (T | number)[] = [];\n private _infiniteTimeWindow = true;\n\n /**\n * @param bufferSize The size of the buffer to replay on subscription\n * @param windowTime The amount of time the buffered items will stay buffered\n * @param timestampProvider An object with a `now()` method that provides the current timestamp. This is used to\n * calculate the amount of time something has been buffered.\n */\n constructor(\n private _bufferSize = Infinity,\n private _windowTime = Infinity,\n private _timestampProvider: TimestampProvider = dateTimestampProvider\n ) {\n super();\n this._infiniteTimeWindow = _windowTime === Infinity;\n this._bufferSize = Math.max(1, _bufferSize);\n this._windowTime = Math.max(1, _windowTime);\n }\n\n next(value: T): void {\n const { isStopped, _buffer, _infiniteTimeWindow, _timestampProvider, _windowTime } = this;\n if (!isStopped) {\n _buffer.push(value);\n !_infiniteTimeWindow && _buffer.push(_timestampProvider.now() + _windowTime);\n }\n this._trimBuffer();\n super.next(value);\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n this._throwIfClosed();\n this._trimBuffer();\n\n const subscription = this._innerSubscribe(subscriber);\n\n const { _infiniteTimeWindow, _buffer } = this;\n // We use a copy here, so reentrant code does not mutate our array while we're\n // emitting it to a new subscriber.\n const copy = _buffer.slice();\n for (let i = 0; i < copy.length && !subscriber.closed; i += _infiniteTimeWindow ? 1 : 2) {\n subscriber.next(copy[i] as T);\n }\n\n this._checkFinalizedStatuses(subscriber);\n\n return subscription;\n }\n\n private _trimBuffer() {\n const { _bufferSize, _timestampProvider, _buffer, _infiniteTimeWindow } = this;\n // If we don't have an infinite buffer size, and we're over the length,\n // use splice to truncate the old buffer values off. Note that we have to\n // double the size for instances where we're not using an infinite time window\n // because we're storing the values and the timestamps in the same array.\n const adjustedBufferSize = (_infiniteTimeWindow ? 1 : 2) * _bufferSize;\n _bufferSize < Infinity && adjustedBufferSize < _buffer.length && _buffer.splice(0, _buffer.length - adjustedBufferSize);\n\n // Now, if we're not in an infinite time window, remove all values where the time is\n // older than what is allowed.\n if (!_infiniteTimeWindow) {\n const now = _timestampProvider.now();\n let last = 0;\n // Search the array for the first timestamp that isn't expired and\n // truncate the buffer up to that point.\n for (let i = 1; i < _buffer.length && (_buffer[i] as number) <= now; i += 2) {\n last = i;\n }\n last && _buffer.splice(0, last + 1);\n }\n }\n}\n", "import { Scheduler } from '../Scheduler';\nimport { Subscription } from '../Subscription';\nimport { SchedulerAction } from '../types';\n\n/**\n * A unit of work to be executed in a `scheduler`. An action is typically\n * created from within a {@link SchedulerLike} and an RxJS user does not need to concern\n * themselves about creating and manipulating an Action.\n *\n * ```ts\n * class Action extends Subscription {\n * new (scheduler: Scheduler, work: (state?: T) => void);\n * schedule(state?: T, delay: number = 0): Subscription;\n * }\n * ```\n *\n * @class Action\n */\nexport class Action extends Subscription {\n constructor(scheduler: Scheduler, work: (this: SchedulerAction, state?: T) => void) {\n super();\n }\n /**\n * Schedules this action on its parent {@link SchedulerLike} for execution. May be passed\n * some context object, `state`. May happen at some point in the future,\n * according to the `delay` parameter, if specified.\n * @param {T} [state] Some contextual data that the `work` function uses when\n * called by the Scheduler.\n * @param {number} [delay] Time to wait before executing the work, where the\n * time unit is implicit and defined by the Scheduler.\n * @return {void}\n */\n public schedule(state?: T, delay: number = 0): Subscription {\n return this;\n }\n}\n", "import type { TimerHandle } from './timerHandle';\ntype SetIntervalFunction = (handler: () => void, timeout?: number, ...args: any[]) => TimerHandle;\ntype ClearIntervalFunction = (handle: TimerHandle) => void;\n\ninterface IntervalProvider {\n setInterval: SetIntervalFunction;\n clearInterval: ClearIntervalFunction;\n delegate:\n | {\n setInterval: SetIntervalFunction;\n clearInterval: ClearIntervalFunction;\n }\n | undefined;\n}\n\nexport const intervalProvider: IntervalProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n setInterval(handler: () => void, timeout?: number, ...args) {\n const { delegate } = intervalProvider;\n if (delegate?.setInterval) {\n return delegate.setInterval(handler, timeout, ...args);\n }\n return setInterval(handler, timeout, ...args);\n },\n clearInterval(handle) {\n const { delegate } = intervalProvider;\n return (delegate?.clearInterval || clearInterval)(handle as any);\n },\n delegate: undefined,\n};\n", "import { Action } from './Action';\nimport { SchedulerAction } from '../types';\nimport { Subscription } from '../Subscription';\nimport { AsyncScheduler } from './AsyncScheduler';\nimport { intervalProvider } from './intervalProvider';\nimport { arrRemove } from '../util/arrRemove';\nimport { TimerHandle } from './timerHandle';\n\nexport class AsyncAction extends Action {\n public id: TimerHandle | undefined;\n public state?: T;\n // @ts-ignore: Property has no initializer and is not definitely assigned\n public delay: number;\n protected pending: boolean = false;\n\n constructor(protected scheduler: AsyncScheduler, protected work: (this: SchedulerAction, state?: T) => void) {\n super(scheduler, work);\n }\n\n public schedule(state?: T, delay: number = 0): Subscription {\n if (this.closed) {\n return this;\n }\n\n // Always replace the current state with the new state.\n this.state = state;\n\n const id = this.id;\n const scheduler = this.scheduler;\n\n //\n // Important implementation note:\n //\n // Actions only execute once by default, unless rescheduled from within the\n // scheduled callback. This allows us to implement single and repeat\n // actions via the same code path, without adding API surface area, as well\n // as mimic traditional recursion but across asynchronous boundaries.\n //\n // However, JS runtimes and timers distinguish between intervals achieved by\n // serial `setTimeout` calls vs. a single `setInterval` call. An interval of\n // serial `setTimeout` calls can be individually delayed, which delays\n // scheduling the next `setTimeout`, and so on. `setInterval` attempts to\n // guarantee the interval callback will be invoked more precisely to the\n // interval period, regardless of load.\n //\n // Therefore, we use `setInterval` to schedule single and repeat actions.\n // If the action reschedules itself with the same delay, the interval is not\n // canceled. If the action doesn't reschedule, or reschedules with a\n // different delay, the interval will be canceled after scheduled callback\n // execution.\n //\n if (id != null) {\n this.id = this.recycleAsyncId(scheduler, id, delay);\n }\n\n // Set the pending flag indicating that this action has been scheduled, or\n // has recursively rescheduled itself.\n this.pending = true;\n\n this.delay = delay;\n // If this action has already an async Id, don't request a new one.\n this.id = this.id ?? this.requestAsyncId(scheduler, this.id, delay);\n\n return this;\n }\n\n protected requestAsyncId(scheduler: AsyncScheduler, _id?: TimerHandle, delay: number = 0): TimerHandle {\n return intervalProvider.setInterval(scheduler.flush.bind(scheduler, this), delay);\n }\n\n protected recycleAsyncId(_scheduler: AsyncScheduler, id?: TimerHandle, delay: number | null = 0): TimerHandle | undefined {\n // If this action is rescheduled with the same delay time, don't clear the interval id.\n if (delay != null && this.delay === delay && this.pending === false) {\n return id;\n }\n // Otherwise, if the action's delay time is different from the current delay,\n // or the action has been rescheduled before it's executed, clear the interval id\n if (id != null) {\n intervalProvider.clearInterval(id);\n }\n\n return undefined;\n }\n\n /**\n * Immediately executes this action and the `work` it contains.\n * @return {any}\n */\n public execute(state: T, delay: number): any {\n if (this.closed) {\n return new Error('executing a cancelled action');\n }\n\n this.pending = false;\n const error = this._execute(state, delay);\n if (error) {\n return error;\n } else if (this.pending === false && this.id != null) {\n // Dequeue if the action didn't reschedule itself. Don't call\n // unsubscribe(), because the action could reschedule later.\n // For example:\n // ```\n // scheduler.schedule(function doWork(counter) {\n // /* ... I'm a busy worker bee ... */\n // var originalAction = this;\n // /* wait 100ms before rescheduling the action */\n // setTimeout(function () {\n // originalAction.schedule(counter + 1);\n // }, 100);\n // }, 1000);\n // ```\n this.id = this.recycleAsyncId(this.scheduler, this.id, null);\n }\n }\n\n protected _execute(state: T, _delay: number): any {\n let errored: boolean = false;\n let errorValue: any;\n try {\n this.work(state);\n } catch (e) {\n errored = true;\n // HACK: Since code elsewhere is relying on the \"truthiness\" of the\n // return here, we can't have it return \"\" or 0 or false.\n // TODO: Clean this up when we refactor schedulers mid-version-8 or so.\n errorValue = e ? e : new Error('Scheduled action threw falsy error');\n }\n if (errored) {\n this.unsubscribe();\n return errorValue;\n }\n }\n\n unsubscribe() {\n if (!this.closed) {\n const { id, scheduler } = this;\n const { actions } = scheduler;\n\n this.work = this.state = this.scheduler = null!;\n this.pending = false;\n\n arrRemove(actions, this);\n if (id != null) {\n this.id = this.recycleAsyncId(scheduler, id, null);\n }\n\n this.delay = null!;\n super.unsubscribe();\n }\n }\n}\n", "import { Action } from './scheduler/Action';\nimport { Subscription } from './Subscription';\nimport { SchedulerLike, SchedulerAction } from './types';\nimport { dateTimestampProvider } from './scheduler/dateTimestampProvider';\n\n/**\n * An execution context and a data structure to order tasks and schedule their\n * execution. Provides a notion of (potentially virtual) time, through the\n * `now()` getter method.\n *\n * Each unit of work in a Scheduler is called an `Action`.\n *\n * ```ts\n * class Scheduler {\n * now(): number;\n * schedule(work, delay?, state?): Subscription;\n * }\n * ```\n *\n * @class Scheduler\n * @deprecated Scheduler is an internal implementation detail of RxJS, and\n * should not be used directly. Rather, create your own class and implement\n * {@link SchedulerLike}. Will be made internal in v8.\n */\nexport class Scheduler implements SchedulerLike {\n public static now: () => number = dateTimestampProvider.now;\n\n constructor(private schedulerActionCtor: typeof Action, now: () => number = Scheduler.now) {\n this.now = now;\n }\n\n /**\n * A getter method that returns a number representing the current time\n * (at the time this function was called) according to the scheduler's own\n * internal clock.\n * @return {number} A number that represents the current time. May or may not\n * have a relation to wall-clock time. May or may not refer to a time unit\n * (e.g. milliseconds).\n */\n public now: () => number;\n\n /**\n * Schedules a function, `work`, for execution. May happen at some point in\n * the future, according to the `delay` parameter, if specified. May be passed\n * some context object, `state`, which will be passed to the `work` function.\n *\n * The given arguments will be processed an stored as an Action object in a\n * queue of actions.\n *\n * @param {function(state: ?T): ?Subscription} work A function representing a\n * task, or some unit of work to be executed by the Scheduler.\n * @param {number} [delay] Time to wait before executing the work, where the\n * time unit is implicit and defined by the Scheduler itself.\n * @param {T} [state] Some contextual data that the `work` function uses when\n * called by the Scheduler.\n * @return {Subscription} A subscription in order to be able to unsubscribe\n * the scheduled work.\n */\n public schedule(work: (this: SchedulerAction, state?: T) => void, delay: number = 0, state?: T): Subscription {\n return new this.schedulerActionCtor(this, work).schedule(state, delay);\n }\n}\n", "import { Scheduler } from '../Scheduler';\nimport { Action } from './Action';\nimport { AsyncAction } from './AsyncAction';\nimport { TimerHandle } from './timerHandle';\n\nexport class AsyncScheduler extends Scheduler {\n public actions: Array> = [];\n /**\n * A flag to indicate whether the Scheduler is currently executing a batch of\n * queued actions.\n * @type {boolean}\n * @internal\n */\n public _active: boolean = false;\n /**\n * An internal ID used to track the latest asynchronous task such as those\n * coming from `setTimeout`, `setInterval`, `requestAnimationFrame`, and\n * others.\n * @type {any}\n * @internal\n */\n public _scheduled: TimerHandle | undefined;\n\n constructor(SchedulerAction: typeof Action, now: () => number = Scheduler.now) {\n super(SchedulerAction, now);\n }\n\n public flush(action: AsyncAction): void {\n const { actions } = this;\n\n if (this._active) {\n actions.push(action);\n return;\n }\n\n let error: any;\n this._active = true;\n\n do {\n if ((error = action.execute(action.state, action.delay))) {\n break;\n }\n } while ((action = actions.shift()!)); // exhaust the scheduler queue\n\n this._active = false;\n\n if (error) {\n while ((action = actions.shift()!)) {\n action.unsubscribe();\n }\n throw error;\n }\n }\n}\n", "import { AsyncAction } from './AsyncAction';\nimport { AsyncScheduler } from './AsyncScheduler';\n\n/**\n *\n * Async Scheduler\n *\n * Schedule task as if you used setTimeout(task, duration)\n *\n * `async` scheduler schedules tasks asynchronously, by putting them on the JavaScript\n * event loop queue. It is best used to delay tasks in time or to schedule tasks repeating\n * in intervals.\n *\n * If you just want to \"defer\" task, that is to perform it right after currently\n * executing synchronous code ends (commonly achieved by `setTimeout(deferredTask, 0)`),\n * better choice will be the {@link asapScheduler} scheduler.\n *\n * ## Examples\n * Use async scheduler to delay task\n * ```ts\n * import { asyncScheduler } from 'rxjs';\n *\n * const task = () => console.log('it works!');\n *\n * asyncScheduler.schedule(task, 2000);\n *\n * // After 2 seconds logs:\n * // \"it works!\"\n * ```\n *\n * Use async scheduler to repeat task in intervals\n * ```ts\n * import { asyncScheduler } from 'rxjs';\n *\n * function task(state) {\n * console.log(state);\n * this.schedule(state + 1, 1000); // `this` references currently executing Action,\n * // which we reschedule with new state and delay\n * }\n *\n * asyncScheduler.schedule(task, 3000, 0);\n *\n * // Logs:\n * // 0 after 3s\n * // 1 after 4s\n * // 2 after 5s\n * // 3 after 6s\n * ```\n */\n\nexport const asyncScheduler = new AsyncScheduler(AsyncAction);\n\n/**\n * @deprecated Renamed to {@link asyncScheduler}. Will be removed in v8.\n */\nexport const async = asyncScheduler;\n", "import { AsyncAction } from './AsyncAction';\nimport { Subscription } from '../Subscription';\nimport { QueueScheduler } from './QueueScheduler';\nimport { SchedulerAction } from '../types';\nimport { TimerHandle } from './timerHandle';\n\nexport class QueueAction extends AsyncAction {\n constructor(protected scheduler: QueueScheduler, protected work: (this: SchedulerAction, state?: T) => void) {\n super(scheduler, work);\n }\n\n public schedule(state?: T, delay: number = 0): Subscription {\n if (delay > 0) {\n return super.schedule(state, delay);\n }\n this.delay = delay;\n this.state = state;\n this.scheduler.flush(this);\n return this;\n }\n\n public execute(state: T, delay: number): any {\n return delay > 0 || this.closed ? super.execute(state, delay) : this._execute(state, delay);\n }\n\n protected requestAsyncId(scheduler: QueueScheduler, id?: TimerHandle, delay: number = 0): TimerHandle {\n // If delay exists and is greater than 0, or if the delay is null (the\n // action wasn't rescheduled) but was originally scheduled as an async\n // action, then recycle as an async action.\n\n if ((delay != null && delay > 0) || (delay == null && this.delay > 0)) {\n return super.requestAsyncId(scheduler, id, delay);\n }\n\n // Otherwise flush the scheduler starting with this action.\n scheduler.flush(this);\n\n // HACK: In the past, this was returning `void`. However, `void` isn't a valid\n // `TimerHandle`, and generally the return value here isn't really used. So the\n // compromise is to return `0` which is both \"falsy\" and a valid `TimerHandle`,\n // as opposed to refactoring every other instanceo of `requestAsyncId`.\n return 0;\n }\n}\n", "import { AsyncScheduler } from './AsyncScheduler';\n\nexport class QueueScheduler extends AsyncScheduler {\n}\n", "import { QueueAction } from './QueueAction';\nimport { QueueScheduler } from './QueueScheduler';\n\n/**\n *\n * Queue Scheduler\n *\n * Put every next task on a queue, instead of executing it immediately\n *\n * `queue` scheduler, when used with delay, behaves the same as {@link asyncScheduler} scheduler.\n *\n * When used without delay, it schedules given task synchronously - executes it right when\n * it is scheduled. However when called recursively, that is when inside the scheduled task,\n * another task is scheduled with queue scheduler, instead of executing immediately as well,\n * that task will be put on a queue and wait for current one to finish.\n *\n * This means that when you execute task with `queue` scheduler, you are sure it will end\n * before any other task scheduled with that scheduler will start.\n *\n * ## Examples\n * Schedule recursively first, then do something\n * ```ts\n * import { queueScheduler } from 'rxjs';\n *\n * queueScheduler.schedule(() => {\n * queueScheduler.schedule(() => console.log('second')); // will not happen now, but will be put on a queue\n *\n * console.log('first');\n * });\n *\n * // Logs:\n * // \"first\"\n * // \"second\"\n * ```\n *\n * Reschedule itself recursively\n * ```ts\n * import { queueScheduler } from 'rxjs';\n *\n * queueScheduler.schedule(function(state) {\n * if (state !== 0) {\n * console.log('before', state);\n * this.schedule(state - 1); // `this` references currently executing Action,\n * // which we reschedule with new state\n * console.log('after', state);\n * }\n * }, 0, 3);\n *\n * // In scheduler that runs recursively, you would expect:\n * // \"before\", 3\n * // \"before\", 2\n * // \"before\", 1\n * // \"after\", 1\n * // \"after\", 2\n * // \"after\", 3\n *\n * // But with queue it logs:\n * // \"before\", 3\n * // \"after\", 3\n * // \"before\", 2\n * // \"after\", 2\n * // \"before\", 1\n * // \"after\", 1\n * ```\n */\n\nexport const queueScheduler = new QueueScheduler(QueueAction);\n\n/**\n * @deprecated Renamed to {@link queueScheduler}. Will be removed in v8.\n */\nexport const queue = queueScheduler;\n", "import { AsyncAction } from './AsyncAction';\nimport { AnimationFrameScheduler } from './AnimationFrameScheduler';\nimport { SchedulerAction } from '../types';\nimport { animationFrameProvider } from './animationFrameProvider';\nimport { TimerHandle } from './timerHandle';\n\nexport class AnimationFrameAction extends AsyncAction {\n constructor(protected scheduler: AnimationFrameScheduler, protected work: (this: SchedulerAction, state?: T) => void) {\n super(scheduler, work);\n }\n\n protected requestAsyncId(scheduler: AnimationFrameScheduler, id?: TimerHandle, delay: number = 0): TimerHandle {\n // If delay is greater than 0, request as an async action.\n if (delay !== null && delay > 0) {\n return super.requestAsyncId(scheduler, id, delay);\n }\n // Push the action to the end of the scheduler queue.\n scheduler.actions.push(this);\n // If an animation frame has already been requested, don't request another\n // one. If an animation frame hasn't been requested yet, request one. Return\n // the current animation frame request id.\n return scheduler._scheduled || (scheduler._scheduled = animationFrameProvider.requestAnimationFrame(() => scheduler.flush(undefined)));\n }\n\n protected recycleAsyncId(scheduler: AnimationFrameScheduler, id?: TimerHandle, delay: number = 0): TimerHandle | undefined {\n // If delay exists and is greater than 0, or if the delay is null (the\n // action wasn't rescheduled) but was originally scheduled as an async\n // action, then recycle as an async action.\n if (delay != null ? delay > 0 : this.delay > 0) {\n return super.recycleAsyncId(scheduler, id, delay);\n }\n // If the scheduler queue has no remaining actions with the same async id,\n // cancel the requested animation frame and set the scheduled flag to\n // undefined so the next AnimationFrameAction will request its own.\n const { actions } = scheduler;\n if (id != null && actions[actions.length - 1]?.id !== id) {\n animationFrameProvider.cancelAnimationFrame(id as number);\n scheduler._scheduled = undefined;\n }\n // Return undefined so the action knows to request a new async id if it's rescheduled.\n return undefined;\n }\n}\n", "import { AsyncAction } from './AsyncAction';\nimport { AsyncScheduler } from './AsyncScheduler';\n\nexport class AnimationFrameScheduler extends AsyncScheduler {\n public flush(action?: AsyncAction): void {\n this._active = true;\n // The async id that effects a call to flush is stored in _scheduled.\n // Before executing an action, it's necessary to check the action's async\n // id to determine whether it's supposed to be executed in the current\n // flush.\n // Previous implementations of this method used a count to determine this,\n // but that was unsound, as actions that are unsubscribed - i.e. cancelled -\n // are removed from the actions array and that can shift actions that are\n // scheduled to be executed in a subsequent flush into positions at which\n // they are executed within the current flush.\n const flushId = this._scheduled;\n this._scheduled = undefined;\n\n const { actions } = this;\n let error: any;\n action = action || actions.shift()!;\n\n do {\n if ((error = action.execute(action.state, action.delay))) {\n break;\n }\n } while ((action = actions[0]) && action.id === flushId && actions.shift());\n\n this._active = false;\n\n if (error) {\n while ((action = actions[0]) && action.id === flushId && actions.shift()) {\n action.unsubscribe();\n }\n throw error;\n }\n }\n}\n", "import { AnimationFrameAction } from './AnimationFrameAction';\nimport { AnimationFrameScheduler } from './AnimationFrameScheduler';\n\n/**\n *\n * Animation Frame Scheduler\n *\n * Perform task when `window.requestAnimationFrame` would fire\n *\n * When `animationFrame` scheduler is used with delay, it will fall back to {@link asyncScheduler} scheduler\n * behaviour.\n *\n * Without delay, `animationFrame` scheduler can be used to create smooth browser animations.\n * It makes sure scheduled task will happen just before next browser content repaint,\n * thus performing animations as efficiently as possible.\n *\n * ## Example\n * Schedule div height animation\n * ```ts\n * // html:
    \n * import { animationFrameScheduler } from 'rxjs';\n *\n * const div = document.querySelector('div');\n *\n * animationFrameScheduler.schedule(function(height) {\n * div.style.height = height + \"px\";\n *\n * this.schedule(height + 1); // `this` references currently executing Action,\n * // which we reschedule with new state\n * }, 0, 0);\n *\n * // You will see a div element growing in height\n * ```\n */\n\nexport const animationFrameScheduler = new AnimationFrameScheduler(AnimationFrameAction);\n\n/**\n * @deprecated Renamed to {@link animationFrameScheduler}. Will be removed in v8.\n */\nexport const animationFrame = animationFrameScheduler;\n", "import { Observable } from '../Observable';\nimport { SchedulerLike } from '../types';\n\n/**\n * A simple Observable that emits no items to the Observer and immediately\n * emits a complete notification.\n *\n * Just emits 'complete', and nothing else.\n *\n * ![](empty.png)\n *\n * A simple Observable that only emits the complete notification. It can be used\n * for composing with other Observables, such as in a {@link mergeMap}.\n *\n * ## Examples\n *\n * Log complete notification\n *\n * ```ts\n * import { EMPTY } from 'rxjs';\n *\n * EMPTY.subscribe({\n * next: () => console.log('Next'),\n * complete: () => console.log('Complete!')\n * });\n *\n * // Outputs\n * // Complete!\n * ```\n *\n * Emit the number 7, then complete\n *\n * ```ts\n * import { EMPTY, startWith } from 'rxjs';\n *\n * const result = EMPTY.pipe(startWith(7));\n * result.subscribe(x => console.log(x));\n *\n * // Outputs\n * // 7\n * ```\n *\n * Map and flatten only odd numbers to the sequence `'a'`, `'b'`, `'c'`\n *\n * ```ts\n * import { interval, mergeMap, of, EMPTY } from 'rxjs';\n *\n * const interval$ = interval(1000);\n * const result = interval$.pipe(\n * mergeMap(x => x % 2 === 1 ? of('a', 'b', 'c') : EMPTY),\n * );\n * result.subscribe(x => console.log(x));\n *\n * // Results in the following to the console:\n * // x is equal to the count on the interval, e.g. (0, 1, 2, 3, ...)\n * // x will occur every 1000ms\n * // if x % 2 is equal to 1, print a, b, c (each on its own)\n * // if x % 2 is not equal to 1, nothing will be output\n * ```\n *\n * @see {@link Observable}\n * @see {@link NEVER}\n * @see {@link of}\n * @see {@link throwError}\n */\nexport const EMPTY = new Observable((subscriber) => subscriber.complete());\n\n/**\n * @param scheduler A {@link SchedulerLike} to use for scheduling\n * the emission of the complete notification.\n * @deprecated Replaced with the {@link EMPTY} constant or {@link scheduled} (e.g. `scheduled([], scheduler)`). Will be removed in v8.\n */\nexport function empty(scheduler?: SchedulerLike) {\n return scheduler ? emptyScheduled(scheduler) : EMPTY;\n}\n\nfunction emptyScheduled(scheduler: SchedulerLike) {\n return new Observable((subscriber) => scheduler.schedule(() => subscriber.complete()));\n}\n", "import { SchedulerLike } from '../types';\nimport { isFunction } from './isFunction';\n\nexport function isScheduler(value: any): value is SchedulerLike {\n return value && isFunction(value.schedule);\n}\n", "import { SchedulerLike } from '../types';\nimport { isFunction } from './isFunction';\nimport { isScheduler } from './isScheduler';\n\nfunction last(arr: T[]): T | undefined {\n return arr[arr.length - 1];\n}\n\nexport function popResultSelector(args: any[]): ((...args: unknown[]) => unknown) | undefined {\n return isFunction(last(args)) ? args.pop() : undefined;\n}\n\nexport function popScheduler(args: any[]): SchedulerLike | undefined {\n return isScheduler(last(args)) ? args.pop() : undefined;\n}\n\nexport function popNumber(args: any[], defaultValue: number): number {\n return typeof last(args) === 'number' ? args.pop()! : defaultValue;\n}\n", "export const isArrayLike = ((x: any): x is ArrayLike => x && typeof x.length === 'number' && typeof x !== 'function');", "import { isFunction } from \"./isFunction\";\n\n/**\n * Tests to see if the object is \"thennable\".\n * @param value the object to test\n */\nexport function isPromise(value: any): value is PromiseLike {\n return isFunction(value?.then);\n}\n", "import { InteropObservable } from '../types';\nimport { observable as Symbol_observable } from '../symbol/observable';\nimport { isFunction } from './isFunction';\n\n/** Identifies an input as being Observable (but not necessary an Rx Observable) */\nexport function isInteropObservable(input: any): input is InteropObservable {\n return isFunction(input[Symbol_observable]);\n}\n", "import { isFunction } from './isFunction';\n\nexport function isAsyncIterable(obj: any): obj is AsyncIterable {\n return Symbol.asyncIterator && isFunction(obj?.[Symbol.asyncIterator]);\n}\n", "/**\n * Creates the TypeError to throw if an invalid object is passed to `from` or `scheduled`.\n * @param input The object that was passed.\n */\nexport function createInvalidObservableTypeError(input: any) {\n // TODO: We should create error codes that can be looked up, so this can be less verbose.\n return new TypeError(\n `You provided ${\n input !== null && typeof input === 'object' ? 'an invalid object' : `'${input}'`\n } where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.`\n );\n}\n", "export function getSymbolIterator(): symbol {\n if (typeof Symbol !== 'function' || !Symbol.iterator) {\n return '@@iterator' as any;\n }\n\n return Symbol.iterator;\n}\n\nexport const iterator = getSymbolIterator();\n", "import { iterator as Symbol_iterator } from '../symbol/iterator';\nimport { isFunction } from './isFunction';\n\n/** Identifies an input as being an Iterable */\nexport function isIterable(input: any): input is Iterable {\n return isFunction(input?.[Symbol_iterator]);\n}\n", "import { ReadableStreamLike } from '../types';\nimport { isFunction } from './isFunction';\n\nexport async function* readableStreamLikeToAsyncGenerator(readableStream: ReadableStreamLike): AsyncGenerator {\n const reader = readableStream.getReader();\n try {\n while (true) {\n const { value, done } = await reader.read();\n if (done) {\n return;\n }\n yield value!;\n }\n } finally {\n reader.releaseLock();\n }\n}\n\nexport function isReadableStreamLike(obj: any): obj is ReadableStreamLike {\n // We don't want to use instanceof checks because they would return\n // false for instances from another Realm, like an