(define-module (zynqmp packages images)
#:use-module (zynqmp packages bootloader)
#:use-module (zynqmp packages linux)
#:use-module (guix packages)
#:use-module (guix modules)
#:use-module (guix gexp)
#:use-module (guix build-system trivial)
#:use-module (gnu services base)
#:use-module (gnu packages base)
#:use-module (gnu system)
#:use-module (gnu system shadow)
#:use-module (gnu system nss)
#:use-module (gnu system image)
#:use-module (gnu image)
#:use-module (gnu bootloader extlinux)
#:use-module (gnu bootloader))
(define root-offset (+ 512 (* 256 1024 1024)))
;; TODO: FDT
(define* (install-xilinx-bootloader fdt)
(with-imported-modules '((zynqmp build bootloader))
#~(begin
(use-modules (zynqmp build bootloader))
(lambda (bootloader device mount-point)
(let* ((bootcfg-file (string-append (getcwd) "/" mount-point "/bootcfg"))
(bootcfg (load bootcfg-file)))
;; Configuration
(mkdir-p (string-append mount-point "/extlinux"))
(call-with-output-file
(string-append mount-point "/extlinux/extlinux.conf")
(lambda (port)
(display (apply string-append (map bootcfg-entry->config-menu-entry bootcfg)) port)))
;; GNU store needed files
(for-each
(lambda (source-file)
(let* ((dest-file (string-append mount-point source-file)))
(mkdir-p (dirname dest-file))
(copy-recursively source-file dest-file)))
(get-required-files bootcfg))
(copy-file (string-append bootloader "/libexec/boot.bin")
(string-append mount-point "/boot.bin"))
(copy-file (string-append bootloader "/libexec/u-boot.itb")
(string-append mount-point "/u-boot.itb"))
;; From the first element extract linux.
;; There can be just one fdt file... the first element should be the newest...
(let* ((entry (list-ref bootcfg 0))
(linux (list-ref entry 1))
(linux-dir (dirname linux)))
(copy-file (string-append linux-dir "/lib/dtbs/" #$fdt ".dtb")
(string-append mount-point "/system.dtb"))))))))
;; This is just a configuration stub. Actually it will write the bootcfg to a file.
;; This file is then consumed by the install bootloader script. And this script
;; will generate the proper configuration
(define* (xilinx-external-bootloader-configuration config entries #:key #:allow-other-keys)
(define all-entries
(append entries (bootloader-configuration-menu-entries config)))
(define (menu-entry->gexp entry)
(let ((label (menu-entry-label entry))
(kernel (menu-entry-linux entry))
(kernel-arguments (menu-entry-linux-arguments entry))
(initrd (menu-entry-initrd entry)))
#~(list #$label #$kernel (list #$@kernel-arguments) #$initrd)))
(define builder
#~(call-with-output-file #$output
(lambda (port)
(write '(list #$@(map menu-entry->gexp all-entries)) port))))
(computed-file "bootcfg" builder))
(define xilinx-bootloader
(bootloader
(inherit extlinux-bootloader)
(name 'xilinx-uboot)
(package u-boot-for-kr260)
(configuration-file-generator xilinx-external-bootloader-configuration)
(installer (install-xilinx-bootloader "xilinx/zynqmp-smk-k26-revA-sck-kr-g-revB"))
(configuration-file "/bootcfg")))
(define root-partition
(partition
(size 'guess)
(label "root")
(file-system "ext4")
(offset root-offset)
;; Disable the metadata_csum and 64bit features of ext4, for compatibility
;; with U-Boot.
(file-system-options (list "-O" "^metadata_csum,^64bit"))
(flags '(boot))
(initializer
#~(lambda* (root #:key
(copy-closures? #t)
(deduplicate? #t)
references-graphs
(register-closures? #t)
system-directory
make-device-nodes
(wal-mode? #t)
#:allow-other-keys)
(initialize-root-partition root
#:bootcfg #f
#:bootcfg-location #f
#:bootloader-package #f
#:bootloader-installer #f
#:copy-closures? copy-closures?
#:deduplicate? deduplicate?
#:references-graphs references-graphs
#:system-directory system-directory
#:make-device-nodes make-device-nodes
#:wal-mode? wal-mode?)))))
(define boot-partition
(partition
(size (* 256 1024 1024))
(label "BOOT")
(file-system "vfat")
(offset 512)
(flags '(boot))
(initializer
(with-imported-modules (source-module-closure
'((guix build utils)
(gnu build install)))
#~(lambda* (root #:key
bootcfg
bootcfg-location
bootloader-package
bootloader-installer
(copy-closures? #t)
(deduplicate? #t)
references-graphs
(register-closures? #t)
system-directory
make-device-nodes
(wal-mode? #t)
#:allow-other-keys)
(use-modules (gnu build install))
(mkdir-p root)
(when bootcfg
(install-boot-config bootcfg bootcfg-location root))
(when bootloader-installer
(display "installing bootloader...\n")
(bootloader-installer bootloader-package #f root)
(display "bootloader installed...\n")))))))
(define os
(operating-system
(host-name "guix")
(timezone "Europe/Prague")
(bootloader
(bootloader-configuration
(bootloader xilinx-bootloader)))
(kernel-arguments '("console=ttyPS1,115200"))
(kernel xilinx-linux-for-zynqmp)
(initrd-modules '())
(file-systems (list)) ; Doesn't matter as replaced by image
(users %base-user-accounts)
(packages %base-packages)
(services %base-services)
(name-service-switch %mdns-host-lookup-nss)))
(define-public zynqmp-base-image
(image
(operating-system os)
(format 'disk-image)
(partition-table-type 'mbr) ;; TODO
(volatile-root? #f)
(partitions
(list root-partition
boot-partition))))
(define-public zynqmp-base-system-image
(package
(name "zynqmp-base-system-image.img")
(version "0")
(source #f)
(build-system trivial-build-system)
(arguments
(list
#:modules '((guix build utils))
#:builder
#~(begin
(use-modules (guix build utils))
(symlink
#$(system-image zynqmp-base-image)
#$output))))
(synopsis #f)
(home-page #f)
(license #f)
(description #f)))