(define-module (skg packages bootloaders) #:use-module (gnu packages) #:use-module (gnu packages assembly) #:use-module (gnu packages base) #:use-module (gnu packages disk) #:use-module (gnu packages bison) #:use-module (gnu packages cdrom) #:use-module (gnu packages check) #:use-module (gnu packages compression) #:use-module (gnu packages cross-base) #:use-module (gnu packages disk) #:use-module (skg packages firmware) #:use-module (gnu packages flex) #:use-module (gnu packages fontutils) #:use-module (gnu packages gcc) #:use-module (gnu packages gettext) #:use-module (gnu packages guile) #:use-module (gnu packages efi) #:use-module (gnu packages linux) #:use-module (gnu packages llvm) #:use-module (gnu packages man) #:use-module (gnu packages mtools) #:use-module (gnu packages ncurses) #:use-module (gnu packages ninja) #:use-module (gnu packages package-management) #:use-module (gnu packages perl) #:use-module (gnu packages pkg-config) #:use-module (gnu packages python) #:use-module (gnu packages python-build) #:use-module (gnu packages python-crypto) #:use-module (gnu packages texinfo) #:use-module (gnu packages tls) #:use-module (gnu packages sdl) #:use-module (gnu packages sphinx) #:use-module (gnu packages serialization) #:use-module (gnu packages swig) #:use-module (gnu packages valgrind) #:use-module (gnu packages version-control) #:use-module (gnu packages virtualization) #:use-module (gnu packages xorg) #:use-module (gnu packages python-build) #:use-module (gnu packages python-web) #:use-module (gnu packages python-xyz) #:use-module (guix build-system gnu) #:use-module (guix build-system meson) #:use-module (guix build-system pyproject) #:use-module (guix build-system trivial) #:use-module (guix download) #:use-module (guix gexp) #:use-module (guix git-download) #:use-module ((guix licenses) #:prefix license:) #:use-module (guix packages) #:use-module (guix utils) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) #:use-module (ice-9 optargs) #:use-module (ice-9 match) #:use-module (ice-9 regex)) (define-public dtc (package (name "dtc") (version "1.7.0") (source (origin (method url-fetch) (uri (string-append "mirror://kernel.org/software/utils/dtc/" "dtc-" version ".tar.gz")) (sha256 (base32 "0cij9399snpn672pdbda8qbxljdkfg068kvv3g5811rz6yslx124")) (patches (search-patches "dtc-meson-cell-overflow.patch")))) (build-system meson-build-system) (arguments (list #:modules '((guix build meson-build-system) (guix build utils) (srfi srfi-26)) #:phases #~(modify-phases %standard-phases (add-after 'unpack 'preparations (lambda _ ;; The version string is usually derived via setuptools-scm, but ;; without the git metadata available this fails. (setenv "SETUPTOOLS_SCM_PRETEND_VERSION" #$version) ;; Needed by setup.py. (setenv "DESTDIR" "/") ;; Native gcc needed by run_test.sh. (setenv "CC" "gcc") ;; /bin/fdt{get,overlay,put} need help finding libfdt.so.1. (setenv "LDFLAGS" (string-append "-Wl,-rpath=" #$output "/lib")))) (add-after 'unpack 'install-doc (lambda _ (with-directory-excursion "Documentation" (for-each (cut install-file <> (string-append #$output "/share/doc/dtc/")) '("dts-format.txt" "dt-object-internal.txt" "manual.txt"))))) (add-after 'unpack 'patch-pkg-config (lambda _ (substitute* '("tests/run_tests.sh") (("pkg-config") #$(pkg-config-for-target)))))))) (native-inputs (append (list bison flex libyaml ninja pkg-config python python-setuptools-scm swig which) (if (member (%current-system) (package-supported-systems valgrind)) (list valgrind) '()))) (inputs (list python)) (home-page "https://www.devicetree.org") (synopsis "Compiles device tree source files") (description "@command{dtc} compiles @uref{http://elinux.org/Device_Tree_Usage, device tree source files} to device tree binary files. These are board description files used by Linux and BSD.") (license license:gpl2+))) (define u-boot (package (name "u-boot") (version "2025.01") (source (origin (method git-fetch) (uri (git-reference (url "https://source.denx.de/u-boot/u-boot.git") (commit (string-append "v" version)))) (file-name (git-file-name name version)) (sha256 (base32 "1i1v86bnixh8hyqbwwr5iwdnnadmg2fqxw9g526fvclsbvl8lz0v")) (patches (search-patches "u-boot-allow-disabling-openssl.patch" "u-boot-rockchip-inno-usb.patch")))) (build-system gnu-build-system) (native-inputs (list bison dtc gnutls flex lz4 ncurses/tinfo perl pkg-config ;for 'make menuconfig' python python-pyelftools python-setuptools python-wheel swig (list util-linux "lib"))) (home-page "https://www.denx.de/wiki/U-Boot/") (synopsis "ARM bootloader") (description "U-Boot is a bootloader used mostly for ARM boards. It also initializes the boards (RAM etc).") (license license:gpl2+))) ;;; This is very similar to the linux-libre-documentation package, since it ;;; reuses the same Makefile-based build system. (define-public u-boot-documentation (package (inherit u-boot) (name "u-boot-documentation") (arguments (list #:make-flags #~(list "HOSTCC=gcc" ;; Avoid treating Sphinx warnings as errors. "SPHINXOPTS=") #:tests? #f #:phases #~(modify-phases %standard-phases (delete 'configure) (replace 'build (lambda* (#:key make-flags #:allow-other-keys) (apply invoke "make" "infodocs" make-flags))) (replace 'install (lambda* (#:key make-flags #:allow-other-keys) (let* ((info-dir (string-append #$output "/share/info")) (info (string-append info-dir "/DasUBoot.info.gz"))) (with-directory-excursion "doc/output" (apply invoke "make" "-C" "texinfo" "install-info" (string-append "infodir=" info-dir) make-flags)))))))) (native-inputs (modify-inputs (package-native-inputs u-boot) (append fontconfig python-sphinx python-sphinx-prompt texinfo which))) (synopsis "U-Boot documentation") (description "This package provides the documentation for U-Boot, as an Info manual."))) (define-public u-boot-tools (package (inherit u-boot) (name "u-boot-tools") (native-inputs (modify-inputs (package-native-inputs u-boot) (prepend python-coverage python-filelock python-pycryptodomex python-pytest python-pytest-xdist))) (arguments `(#:make-flags '("HOSTCC=gcc") #:test-target "tcheck" #:phases (modify-phases %standard-phases (add-after 'unpack 'patch (lambda* (#:key inputs #:allow-other-keys) (substitute* "Makefile" (("/bin/pwd") (which "pwd")) (("/bin/false") (which "false"))) (substitute* "tools/dtoc/fdt_util.py" (("'cc'") "'gcc'")) (substitute* "tools/u_boot_pylib/test_util.py" ;; python3-coverage is simply called coverage in guix. (("python3-coverage") "coverage") ;; Don't require 100% coverage since it's brittle and can ;; fail with newer versions of coverage or dependencies. (("raise ValueError\\('Test coverage failure'\\)") "print('Continuing anyway since Guix does not care :O')")) (substitute* "test/run" ;; Make it easier to find test failures. (("#!/bin/bash") "#!/bin/bash -x") ;; This test would require git. (("\\./tools/patman/patman") (which "true")) ;; FIXME: test fails, needs further investiation (("run_test \"binman\"") "# run_test \"binman\"") ;; FIXME: tests fail without kwbimage, i.e. openssl. (("run_test \"sandbox_noinst\"") "# run_test \"sandbox_noinst\"") (("run_test \"sandbox_vpl\"") "# run_test \"sandbox_vpl\"") ;; FIXME: code coverage not working (("run_test \"binman code coverage\"") "# run_test \"binman code coverage\"") ;; This test would require internet access. (("\\./tools/buildman/buildman") (which "true"))) (substitute* "test/py/tests/test_sandbox_exit.py" (("def test_ctrl_c") "@pytest.mark.skip(reason='Guix has problems with SIGINT') def test_ctrl_c")) ;; Test against the tools being installed rather than tools built ;; for "sandbox" target. (substitute* "test/image/test-imagetools.sh" (("BASEDIR=sandbox") "BASEDIR=.")) (for-each (lambda (file) (substitute* file ;; Disable features that require OpenSSL due ;; to GPL/Openssl license incompatibilities. ;; See https://bugs.gnu.org/34717 for ;; details. (("CONFIG_FIT_SIGNATURE=y") "CONFIG_FIT_SIGNATURE=n CONFIG_UT_LIB_ASN1=n CONFIG_TOOLS_LIBCRYPTO=n CONFIG_TOOLS_KWBIMAGE=n") ;; Catch instances of implied CONFIG_FIG_SIGNATURE ;; with VPL targets (("CONFIG_SANDBOX_VPL=y") "CONFIG_SANDBOX_VPL=y CONFIG_FIT_SIGNATURE=n CONFIG_VPL_FIT_SIGNATURE=n CONFIG_TOOLS_LIBCRYPTO=n CONFIG_TOOLS_KWBIMAGE=n") ;; This test requires a sound system, which is un-used ;; in u-boot-tools. (("CONFIG_SOUND=y") "CONFIG_SOUND=n"))) (find-files "configs" "sandbox_.*defconfig$|tools-only_defconfig")))) (replace 'configure (lambda* (#:key make-flags #:allow-other-keys) (apply invoke "make" "tools-only_defconfig" make-flags))) (replace 'build (lambda* (#:key inputs make-flags #:allow-other-keys) (apply invoke "make" "tools-all" make-flags))) (replace 'install (lambda* (#:key outputs #:allow-other-keys) (let* ((out (assoc-ref outputs "out")) (bin (string-append out "/bin"))) (for-each (lambda (name) (install-file name bin)) '("tools/netconsole" "tools/jtagconsole" "tools/gen_eth_addr" "tools/gen_ethaddr_crc" "tools/img2srec" "tools/mkenvimage" "tools/dumpimage" "tools/mkimage" "tools/kwboot" "tools/proftool" "tools/fdtgrep" "tools/env/fw_printenv" "tools/sunxi-spl-image-builder"))))) (delete 'check) (add-after 'install 'check (lambda* (#:key make-flags test-target tests? #:allow-other-keys) (when tests? (invoke "test/image/test-imagetools.sh")))) ;; Only run full test suite on x86_64 systems, as many tests ;; assume x86_64. ,@(if (string-match "^x86_64-linux" (or (%current-target-system) (%current-system))) '((add-after 'check 'check-x86 (lambda* (#:key make-flags test-target tests? #:allow-other-keys) (when tests? (begin (apply invoke "make" "mrproper" make-flags) (setenv "SDL_VIDEODRIVER" "dummy") (setenv "PAGER" "cat") (apply invoke "make" test-target make-flags)))))) '())))) (description (string-append (package-description u-boot) " This package provides board-independent tools " "of U-Boot.")))) (define-public python-u-boot-pylib (package (inherit u-boot) (name "python-u-boot-pylib") (build-system pyproject-build-system) (arguments (list #:phases #~(modify-phases %standard-phases (add-after 'unpack 'chdir (lambda _ (chdir "tools/u_boot_pylib"))) (add-after 'chdir 'list-package (lambda _ (let ((port (open-file "pyproject.toml" "a"))) (display "[tool.setuptools.packages.find]\n" port) (display "where = [\"..\"]\n" port) (display "include = [\"u_boot_pylib*\"]" port) (close-port port)))) (replace 'check (lambda* (#:key tests? #:allow-other-keys) (when tests? (invoke "./u_boot_pylib"))))))) (synopsis "U-Boot Python library") (description "This package provides common Python code used by some of the commands part of the U-Boot project, such as Patman."))) ;;; This is packaged separately, as it can be used in other contexts than for ;;; U-Boot development. (define-public patman (package (inherit u-boot) (name "patman") (build-system pyproject-build-system) (arguments ;; The test suite strongly relies on the git metadata being available (23 ;; failed, 14 passed). (list #:tests? #f #:phases #~(modify-phases %standard-phases ;; Patman fails to run during 'sanity-check phase, as it needs to be ;; run within a git directory. (delete 'sanity-check) (add-after 'unpack 'chdir (lambda _ (chdir "tools/patman"))) (add-after 'install 'wrap-script (lambda* (#:key inputs #:allow-other-keys) (wrap-script (string-append #$output "/bin/patman") `("PATH" ":" prefix (,(string-append #$(this-package-input "git") "/bin"))) `("GIT_EXEC_PATH" ":" prefix (,(dirname (search-input-file inputs "libexec/git-core/git-commit")) ,(dirname (search-input-file inputs "libexec/git-core/git-send-email")))))))))) (inputs (list git `(,git "send-email") guile-3.0/pinned ;for wrap-script python-pygit2 python-requests python-u-boot-pylib)) (synopsis "Patch automation tool") (description "Patman is a patch automation script which: @itemize @item Creates patches directly from your branch @item Cleans them up by removing unwanted tags @item Inserts a cover letter with change lists @item Runs the patches through automated checks @item Optionally emails them out to selected people. @end itemize"))) (define*-public (make-u-boot-package board triplet #:key defconfig configs name-suffix append-description (u-boot u-boot)) "Return a U-Boot package for BOARD cross-compiled for TRIPLET with the optional DEFCONFIG file and optional configuration changes from CONFIGS. TRIPLET may also be set to #f to disable cross-compilation. NAME-SUFFIX is appended to the package name, while APPEND-DESCRIPTION is appended to the package description. U-BOOT can be used when a fork or a different version of U-Boot must be used." (let ((native-build? (lambda () (or (not triplet) ;disable cross-compilation (string=? (%current-system) (gnu-triplet->nix-system triplet)))))) (package (inherit u-boot) (name (string-append (downstream-package-name "u-boot-" board) (or name-suffix ""))) (description (if append-description (string-append (package-description u-boot) "\n\n" append-description) (package-description u-boot))) (build-system gnu-build-system) (arguments (substitute-keyword-arguments (package-arguments u-boot) ((#:target _ #f) (and (not (native-build?)) triplet)) ((#:modules modules '()) `((ice-9 ftw) (srfi srfi-1) (guix build gnu-build-system) (guix build kconfig) (guix build utils) ,@modules)) ((#:imported-modules imported-modules '()) `((guix build kconfig) ,@%default-gnu-imported-modules ,@imported-modules)) ((#:test-target _ "test") "test") ((#:make-flags make-flags '()) #~(list "HOSTCC=gcc" "KBUILD_VERBOSE=1" #$@(if (not (native-build?)) (list (string-append "CROSS_COMPILE=" triplet "-")) '()) #$@make-flags)) ((#:phases phases '%standard-phases) #~(modify-phases #$phases (replace 'configure (lambda* (#:key make-flags #:allow-other-keys) (let* ((config-name (string-append #$board "_defconfig")) (config-file (string-append "configs/" config-name)) (defconfig #$defconfig) (configs '#$configs)) (when defconfig ;; Replace the board-specific defconfig with the given ;; one. (copy-file defconfig config-file)) (if (file-exists? config-file) (begin (when configs (modify-defconfig config-file configs)) (apply invoke "make" `(,@make-flags ,config-name)) (verify-config ".config" config-file)) (begin (display "invalid board name; valid board names are:" (current-error-port)) (let ((suffix-len (string-length "_defconfig")) (entries (scandir "configs"))) (for-each (lambda (file-name) (when (string-suffix? "_defconfig" file-name) (format (current-error-port) "- ~A\n" (string-drop-right file-name suffix-len)))) (sort entries string-ci<))) (error "invalid boardname ~s" #$board)))))) (add-after 'configure 'disable-tools-libcrypto ;; Disable libcrypto due to GPL and OpenSSL license ;; incompatibilities (lambda _ (substitute* ".config" (("CONFIG_TOOLS_LIBCRYPTO=.*$") "CONFIG_TOOLS_LIBCRYPTO=n CONFIG_TOOLS_KWBIMAGE=n")))) (replace 'install (lambda _ (let ((libexec (string-append #$output "/libexec")) (uboot-files (append (remove ;; Those would not be reproducible ;; because of the randomness used to ;; produce them. It's expected that the ;; user will use u-boot-tools to generate ;; them instead. (lambda (name) (string-suffix? "sunxi-spl-with-ecc.bin" name)) (find-files "." ".*\\.(bin|efi|img|imx|spl|itb|dtb|rksd)$")) (find-files "." "^(MLO|SPL)$")))) (mkdir-p libexec) (install-file ".config" libexec) ;; Useful for "qemu -kernel". (install-file "u-boot" libexec) (for-each (lambda (file) (let ((target-file (string-append libexec "/" file))) (mkdir-p (dirname target-file)) (copy-file file target-file))) uboot-files))))))))))) (define*-public (make-u-boot-sunxi64-package board triplet ;;scp-firmware #:key defconfig configs) (let ((base (make-u-boot-package board triplet #:defconfig defconfig #:configs configs))) (package (inherit base) (arguments (substitute-keyword-arguments (package-arguments base) ((#:phases phases) #~(modify-phases #$phases (add-after 'unpack 'set-environment (lambda* (#:key native-inputs inputs #:allow-other-keys) ;;(setenv "SCP" (search-input-file ;; (or native-inputs inputs) "libexec/scp.bin")) (setenv "BL31" (search-input-file inputs "bl31.bin")))))))) ;;(native-inputs ;; (modify-inputs (package-native-inputs base) ;; (append (force scp-firmware)))) (inputs (modify-inputs (package-inputs base) (append arm-trusted-firmware-sun50i-h616)))))) (define-public u-boot-rg35xx (make-u-boot-sunxi64-package "anbernic_rg35xx_h700" "aarch64-linux-gnu" ))