mirror of
https://git.in.rschanz.org/ryan77627/guix.git
synced 2024-12-24 05:18:07 -05:00
Merge branch 'master' into core-updates
This commit is contained in:
commit
062c7e43ed
30 changed files with 2567 additions and 1314 deletions
|
@ -4791,7 +4791,9 @@ The general syntax is:
|
|||
guix hash @var{option} @var{file}
|
||||
@end example
|
||||
|
||||
@command{guix hash} has the following options:
|
||||
When @var{file} is @code{-} (a hyphen), @command{guix hash} computes the
|
||||
hash of data read from standard input. @command{guix hash} has the
|
||||
following options:
|
||||
|
||||
@table @code
|
||||
|
||||
|
@ -12240,6 +12242,58 @@ which may be insufficient for some operations.
|
|||
The file name of the qcow2 image.
|
||||
@end table
|
||||
|
||||
The default @command{run-vm.sh} script that is returned by an invokation of
|
||||
@command{guix system vm} does not add a @command{-net user} flag by default.
|
||||
To get network access from within the vm add the @code{(dhcp-client-service)}
|
||||
to your system definition and start the VM using
|
||||
@command{`guix system vm config.scm` -net user}. An important caveat of using
|
||||
@command{-net user} for networking is that @command{ping} will not work, because
|
||||
it uses the ICMP protocol. You'll have to use a different command to check for
|
||||
network connectivity, like for example @command{curl}.
|
||||
|
||||
@subsubsection Connecting Through SSH
|
||||
|
||||
To enable SSH inside a VM you need to add a SSH server like @code{(dropbear-service)}
|
||||
or @code{(lsh-service)} to your VM. The @code{(lsh-service}) doesn't currently
|
||||
boot unsupervised. It requires you to type some characters to initialize the
|
||||
randomness generator. In addition you need to forward the SSH port, 22 by
|
||||
default, to the host. You can do this with
|
||||
|
||||
@example
|
||||
`guix system vm config.scm` -net user,hostfwd=tcp::10022-:22
|
||||
@end example
|
||||
|
||||
To connect to the VM you can run
|
||||
|
||||
@example
|
||||
ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p 10022
|
||||
@end example
|
||||
|
||||
The @command{-p} tells @command{ssh} the port you want to connect to.
|
||||
@command{-o UserKnownHostsFile=/dev/null} prevents @command{ssh} from complaining
|
||||
every time you modify your @command{config.scm} file and the
|
||||
@command{-o StrictHostKeyChecking=no} prevents you from having to allow a
|
||||
connection to an unknown host every time you connect.
|
||||
|
||||
@subsubsection Using @command{virt-viewer} with Spice
|
||||
|
||||
As an alternative to the default @command{qemu} graphical client you can
|
||||
use the @command{remote-viewer} from the @command{virt-viewer} package. To
|
||||
connect pass the @command{-spice port=5930,disable-ticketing} flag to
|
||||
@command{qemu}. See previous section for further information on how to do this.
|
||||
|
||||
Spice also allows you to do some nice stuff like share your clipboard with your
|
||||
VM. To enable that you'll also have to pass the following flags to @command{qemu}:
|
||||
|
||||
@example
|
||||
-device virtio-serial-pci,id=virtio-serial0,max_ports=16,bus=pci.0,addr=0x5
|
||||
-chardev spicevmc,name=vdagent,id=vdagent
|
||||
-device virtserialport,nr=1,bus=virtio-serial0.0,chardev=vdagent,
|
||||
name=com.redhat.spice.0
|
||||
@end example
|
||||
|
||||
You'll also need to add the @pxref{Miscellaneous Services, Spice service}.
|
||||
|
||||
@node Defining Services
|
||||
@subsection Defining Services
|
||||
|
||||
|
|
|
@ -734,6 +734,7 @@ dist_patch_DATA = \
|
|||
%D%/packages/patches/openjpeg-CVE-2016-5157.patch \
|
||||
%D%/packages/patches/openjpeg-CVE-2016-7163.patch \
|
||||
%D%/packages/patches/openjpeg-use-after-free-fix.patch \
|
||||
%D%/packages/patches/openocd-nrf52.patch \
|
||||
%D%/packages/patches/openssh-memory-exhaustion.patch \
|
||||
%D%/packages/patches/openssl-runpath.patch \
|
||||
%D%/packages/patches/openssl-1.1.0-c-rehash-in.patch \
|
||||
|
|
|
@ -406,13 +406,13 @@ (define-public libchop
|
|||
(define-public borg
|
||||
(package
|
||||
(name "borg")
|
||||
(version "1.0.7")
|
||||
(version "1.0.8")
|
||||
(source (origin
|
||||
(method url-fetch)
|
||||
(uri (pypi-uri "borgbackup" version))
|
||||
(sha256
|
||||
(base32
|
||||
"1l9iw55w5x51yxl3q89cf6avg80lajxvc8qz584hrsmnk6i56cr0"))
|
||||
"1fdfi0yzzdrrlml6780n4fh61sqm7pw6fcd1y67kfkvw8hy5c0k9"))
|
||||
(modules '((guix build utils)))
|
||||
(snippet
|
||||
'(for-each
|
||||
|
|
|
@ -29,7 +29,7 @@ (define-module (gnu packages ccache)
|
|||
(define-public ccache
|
||||
(package
|
||||
(name "ccache")
|
||||
(version "3.3.2")
|
||||
(version "3.3.3")
|
||||
(source
|
||||
(origin
|
||||
(method url-fetch)
|
||||
|
@ -37,7 +37,7 @@ (define-public ccache
|
|||
version ".tar.xz"))
|
||||
(sha256
|
||||
(base32
|
||||
"0c25l78hi36682l9cyxca78i8sdkmgmv9afip1s21y6q4g5qaxlh"))))
|
||||
"1v04ky2mhvx8gnqfbs9x2vvf4i9mzph4fwdg72s9xyhwv92sf0iv"))))
|
||||
(build-system gnu-build-system)
|
||||
(native-inputs `(("perl" ,perl) ;for test.sh
|
||||
("which" ,(@ (gnu packages base) which))))
|
||||
|
|
|
@ -320,14 +320,14 @@ (define-public cups
|
|||
(define-public hplip
|
||||
(package
|
||||
(name "hplip")
|
||||
(version "3.16.8")
|
||||
(version "3.16.10")
|
||||
(source (origin
|
||||
(method url-fetch)
|
||||
(uri (string-append "mirror://sourceforge/hplip/hplip/" version
|
||||
"/hplip-" version ".tar.gz"))
|
||||
(sha256
|
||||
(base32
|
||||
"1svcalf2nc7mvxndp9zz3xp43w66z45rrsr5syl8fx61a6p6gnm9"))))
|
||||
"117f1p0splg51ljn4nn97c0mbl0jba440ahb3d8njq7p6h1lxd25"))))
|
||||
(build-system gnu-build-system)
|
||||
(home-page "http://hplipopensource.com/")
|
||||
(synopsis "HP Printer Drivers")
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
|
||||
;;; Copyright © 2016 John Darrington <jmd@gnu.org>
|
||||
;;; Copyright © 2016 ng0 <ng0@we.make.ritual.n0.is>
|
||||
;;; Copyright © 2016 Tobias Geerinckx-Rice <me@tobias.gr>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
|
@ -23,6 +24,7 @@
|
|||
|
||||
(define-module (gnu packages dns)
|
||||
#:use-module (gnu packages autotools)
|
||||
#:use-module (gnu packages base)
|
||||
#:use-module (gnu packages databases)
|
||||
#:use-module (gnu packages groff)
|
||||
#:use-module (gnu packages linux)
|
||||
|
@ -161,3 +163,40 @@ (define-public libasr
|
|||
license:bsd-3
|
||||
(license:non-copyleft "file://LICENSE") ; includes.h
|
||||
license:openssl))))
|
||||
|
||||
(define-public yadifa
|
||||
(package
|
||||
(name "yadifa")
|
||||
(version "2.2.1-6281")
|
||||
(source
|
||||
(origin
|
||||
(method url-fetch)
|
||||
(uri (string-append "http://cdn.yadifa.eu/sites/default/files/releases/"
|
||||
name "-" version ".tar.gz"))
|
||||
(sha256
|
||||
(base32
|
||||
"0vj71z7i9lfbnp93k28aplwldp5mfli0kvrbwmha6fjha6kcr910"))))
|
||||
(build-system gnu-build-system)
|
||||
(native-inputs
|
||||
`(("which" ,which)))
|
||||
(inputs
|
||||
`(("openssl" ,openssl)))
|
||||
(arguments
|
||||
`(#:phases (modify-phases %standard-phases
|
||||
(add-before 'configure 'omit-example-configurations
|
||||
(lambda _ (substitute* "Makefile.in"
|
||||
((" (etc|var)") "")))))
|
||||
#:configure-flags (list "--sysconfdir=/etc" "--localstatedir=/var"
|
||||
"--enable-shared" "--disable-static"
|
||||
"--enable-messages" "--enable-ctrl"
|
||||
;; NSID is a rarely-used debugging aid, that also
|
||||
;; causes the build to fail. Just disable it.
|
||||
"--disable-nsid")))
|
||||
(home-page "http://www.yadifa.eu/")
|
||||
(synopsis "Authoritative DNS name server")
|
||||
(description "YADIFA is an authorative name server for the Domain Name
|
||||
System (DNS). It aims for both higher performance and a smaller memory
|
||||
footprint than other implementations, while remaining fully RFC-compliant.
|
||||
YADIFA supports dynamic record updates and the Domain Name System Security
|
||||
Extensions (DNSSEC).")
|
||||
(license license:bsd-3)))
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
|
||||
;;; Copyright © 2016 Theodoros Foradis <theodoros.for@openmailbox.org>
|
||||
;;; Copyright © 2016 David Craven <david@craven.ch>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
|
@ -28,10 +29,15 @@ (define-module (gnu packages embedded)
|
|||
#:use-module (guix build-system trivial)
|
||||
#:use-module (guix build utils)
|
||||
#:use-module (gnu packages)
|
||||
#:use-module (gnu packages autotools)
|
||||
#:use-module (gnu packages cross-base)
|
||||
#:use-module (gnu packages flex)
|
||||
#:use-module (gnu packages gcc)
|
||||
#:use-module (gnu packages gdb)
|
||||
#:use-module (gnu packages libftdi)
|
||||
#:use-module (gnu packages libusb)
|
||||
#:use-module (gnu packages perl)
|
||||
#:use-module (gnu packages pkg-config)
|
||||
#:use-module (gnu packages texinfo))
|
||||
|
||||
;; We must not use the released GCC sources here, because the cross-compiler
|
||||
|
@ -223,3 +229,136 @@ (define-public arm-none-eabi-toolchain-6
|
|||
(define-public arm-none-eabi-nano-toolchain-6
|
||||
(arm-none-eabi-toolchain gcc-arm-none-eabi-6
|
||||
newlib-nano-arm-none-eabi))
|
||||
|
||||
(define-public gdb-arm-none-eabi
|
||||
(package
|
||||
(inherit gdb)
|
||||
(name "gdb-arm-none-eabi")
|
||||
(arguments
|
||||
`(#:configure-flags '("--target=arm-none-eabi"
|
||||
"--enable-multilib"
|
||||
"--enable-interwork"
|
||||
"--enable-languages=c,c++"
|
||||
"--disable-nls")
|
||||
,@(package-arguments gdb)))))
|
||||
|
||||
(define-public libjaylink
|
||||
;; No release tarballs available.
|
||||
(let ((commit "faa2a433fdd3de211728f3da5921133214af9dd3")
|
||||
(revision "1"))
|
||||
(package
|
||||
(name "libjaylink")
|
||||
(version (string-append "0.1.0-" revision "."
|
||||
(string-take commit 7)))
|
||||
(source (origin
|
||||
(method git-fetch)
|
||||
(uri (git-reference
|
||||
(url "git://git.zapb.de/libjaylink.git")
|
||||
(commit commit)))
|
||||
(file-name (string-append name "-" version "-checkout"))
|
||||
(sha256
|
||||
(base32
|
||||
"02crr56csz8whq3q4mrmdzzgwp5b0qvxm0fb18drclc3zj44yxl2"))))
|
||||
(build-system gnu-build-system)
|
||||
(native-inputs
|
||||
`(("autoconf" ,autoconf)
|
||||
("automake" ,automake)
|
||||
("libtool" ,libtool)
|
||||
("pkg-config" ,pkg-config)))
|
||||
(inputs
|
||||
`(("libusb" ,libusb)))
|
||||
(arguments
|
||||
`(#:phases
|
||||
(modify-phases %standard-phases
|
||||
(add-before 'configure 'autoreconf
|
||||
(lambda _
|
||||
(zero? (system* "autoreconf" "-vfi")))))))
|
||||
(home-page "http://repo.or.cz/w/libjaylink.git")
|
||||
(synopsis "Library to interface Segger J-Link devices")
|
||||
(description "libjaylink is a shared library written in C to access
|
||||
SEGGER J-Link and compatible devices.")
|
||||
(license license:gpl2+))))
|
||||
|
||||
(define-public jimtcl
|
||||
(package
|
||||
(name "jimtcl")
|
||||
(version "0.77")
|
||||
(source (origin
|
||||
(method url-fetch)
|
||||
(uri (string-append
|
||||
"https://github.com/msteveb/jimtcl"
|
||||
"/archive/" version ".tar.gz"))
|
||||
(file-name (string-append name "-" version ".tar.gz"))
|
||||
(sha256
|
||||
(base32
|
||||
"1cmk3qscqckg70chjyimzxa2qcka4qac0j4wq908kiijp45cax08"))))
|
||||
(build-system gnu-build-system)
|
||||
(arguments
|
||||
`(#:phases
|
||||
(modify-phases %standard-phases
|
||||
;; Doesn't use autoconf.
|
||||
(replace 'configure
|
||||
(lambda* (#:key outputs #:allow-other-keys)
|
||||
(let ((out (assoc-ref outputs "out")))
|
||||
(zero? (system* "./configure"
|
||||
(string-append "--prefix=" out)))))))))
|
||||
(home-page "http://jim.tcl.tk")
|
||||
(synopsis "Small footprint Tcl implementation")
|
||||
(description "Jim is a small footprint implementation of the Tcl programming
|
||||
language.")
|
||||
(license license:bsd-2)))
|
||||
|
||||
(define-public openocd
|
||||
;; FIXME: Use tarball release after nrf52 patch is merged.
|
||||
(let ((commit "674141e8a7a6413cb803d90c2a20150260015f81")
|
||||
(revision "1"))
|
||||
(package
|
||||
(name "openocd")
|
||||
(version (string-append "0.9.0-" revision "."
|
||||
(string-take commit 7)))
|
||||
(source (origin
|
||||
(method git-fetch)
|
||||
(uri (git-reference
|
||||
(url "git://git.code.sf.net/p/openocd/code.git")
|
||||
(commit commit)))
|
||||
(sha256
|
||||
(base32
|
||||
"1i86jp0wawq78d73z8hp7q1pn7lmlvhjjr19f7299h4w40a5jf8j"))
|
||||
(file-name (string-append name "-" version "-checkout"))
|
||||
(patches
|
||||
(search-patches "openocd-nrf52.patch"))))
|
||||
(build-system gnu-build-system)
|
||||
(native-inputs
|
||||
`(("autoconf" ,autoconf)
|
||||
("automake" ,automake)
|
||||
("libtool" ,libtool)
|
||||
("pkg-config" ,pkg-config)))
|
||||
(inputs
|
||||
`(("hidapi" ,hidapi)
|
||||
("jimtcl" ,jimtcl)
|
||||
("libftdi" ,libftdi)
|
||||
("libjaylink" ,libjaylink)
|
||||
("libusb-compat" ,libusb-compat)))
|
||||
(arguments
|
||||
'(#:configure-flags
|
||||
(append (list "--disable-werror"
|
||||
"--disable-internal-jimtcl"
|
||||
"--disable-internal-libjaylink")
|
||||
(map (lambda (programmer)
|
||||
(string-append "--enable-" programmer))
|
||||
'("amtjtagaccel" "armjtagew" "buspirate" "ftdi"
|
||||
"gw16012" "jlink" "oocd_trace" "opendous" "osbdm"
|
||||
"parport" "aice" "cmsis-dap" "dummy" "jtag_vpi"
|
||||
"remote-bitbang" "rlink" "stlink" "ti-icdi" "ulink"
|
||||
"usbprog" "vsllink" "usb-blaster-2" "usb_blaster"
|
||||
"presto" "openjtag")))
|
||||
#:phases
|
||||
(modify-phases %standard-phases
|
||||
(add-before 'configure 'autoreconf
|
||||
(lambda _
|
||||
(zero? (system* "autoreconf" "-vfi")))))))
|
||||
(home-page "http://openocd.org")
|
||||
(synopsis "On-Chip Debugger")
|
||||
(description "OpenOCD provides on-chip programming and debugging support
|
||||
with a layered architecture of JTAG interface and TAP support.")
|
||||
(license license:gpl2))))
|
||||
|
|
|
@ -79,3 +79,22 @@ (define-public flex
|
|||
executes the corresponding C code.")
|
||||
(license (non-copyleft "file://COPYING"
|
||||
"See COPYING in the distribution."))))
|
||||
|
||||
(define-public flex-2.6.1
|
||||
;; The kservice and solid packages use flex. extra-cmake-modules
|
||||
;; forces C89 for all C files for compatibility with windows.
|
||||
;; Flex 2.6.0 generates a lexer containing a single line comment. Single
|
||||
;; line comments are part of the C99 standard, so the lexer won't compile
|
||||
;; if C89 is used.
|
||||
(package
|
||||
(inherit flex)
|
||||
(version "2.6.1")
|
||||
(source (origin
|
||||
(method url-fetch)
|
||||
(uri (string-append
|
||||
"https://github.com/westes/flex"
|
||||
"/releases/download/v" version "/"
|
||||
"flex-" version ".tar.gz"))
|
||||
(sha256
|
||||
(base32
|
||||
"0fy14c35yz2m1n1m4f02by3501fn0cca37zn7jp8lpp4b3kgjhrw"))))))
|
||||
|
|
|
@ -329,7 +329,7 @@ (define-public cmatrix
|
|||
(define-public chess
|
||||
(package
|
||||
(name "chess")
|
||||
(version "6.2.3")
|
||||
(version "6.2.4")
|
||||
(source
|
||||
(origin
|
||||
(method url-fetch)
|
||||
|
@ -337,9 +337,9 @@ (define-public chess
|
|||
".tar.gz"))
|
||||
(sha256
|
||||
(base32
|
||||
"10hvnfhj9bkpz80x20jgxyqvgvrcgfdp8sfcbcrf1dgjn9v936bq"))))
|
||||
"1vw2w3jwnmn44d5vsw47f8y70xvxcsz9m5msq9fgqlzjch15qhiw"))))
|
||||
(build-system gnu-build-system)
|
||||
(home-page "http://www.gnu.org/software/chess")
|
||||
(home-page "https://www.gnu.org/software/chess")
|
||||
(synopsis "Full chess implementation")
|
||||
(description "GNU Chess is a chess engine. It allows you to compete
|
||||
against the computer in a game of chess, either through the default terminal
|
||||
|
|
|
@ -410,7 +410,8 @@ (define-public icecat
|
|||
("glib" ,glib)
|
||||
("gstreamer" ,gstreamer)
|
||||
("gst-plugins-base" ,gst-plugins-base)
|
||||
("gtk+" ,gtk+-2)
|
||||
("gtk+" ,gtk+)
|
||||
("gtk+-2" ,gtk+-2)
|
||||
("pango" ,pango)
|
||||
("freetype" ,freetype)
|
||||
("hunspell" ,hunspell)
|
||||
|
@ -454,7 +455,7 @@ (define-public icecat
|
|||
;; practice somehow. See <http://hydra.gnu.org/build/378133>.
|
||||
#:validate-runpath? #f
|
||||
|
||||
#:configure-flags '("--enable-default-toolkit=cairo-gtk2"
|
||||
#:configure-flags '("--enable-default-toolkit=cairo-gtk3"
|
||||
"--enable-pango"
|
||||
"--enable-gio"
|
||||
"--enable-svg"
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -4,6 +4,7 @@
|
|||
;;; Copyright © 2015 Andy Wingo <wingo@igalia.com>
|
||||
;;; Copyright © 2015, 2016 Ricardo Wurmus <rekado@elephly.net>
|
||||
;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
|
||||
;;; Copyright © 2016 Theodoros Foradis <theodoros.for@openmailbox.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
|
@ -29,6 +30,7 @@ (define-module (gnu packages libusb)
|
|||
#:use-module (guix build-system gnu)
|
||||
#:use-module (guix build-system glib-or-gtk)
|
||||
#:use-module (guix build-system python)
|
||||
#:use-module (gnu packages autotools)
|
||||
#:use-module (gnu packages gnupg)
|
||||
#:use-module (gnu packages gtk)
|
||||
#:use-module (gnu packages linux)
|
||||
|
@ -201,3 +203,39 @@ (define-public gmtp
|
|||
(MTP), which allows media files to be transferred to and from many portable
|
||||
devices.")
|
||||
(license bsd-3)))
|
||||
|
||||
(define-public hidapi
|
||||
(package
|
||||
(name "hidapi")
|
||||
(version "0.8.0-rc1")
|
||||
(source (origin
|
||||
(method url-fetch)
|
||||
(uri (string-append "https://github.com/signal11/hidapi/archive/hidapi-"
|
||||
version ".tar.gz"))
|
||||
(sha256
|
||||
(base32
|
||||
"0qdgyj9rgb7n0nk3ghfswrhzzknxqn4ibn3wj8g4r828pw07451w"))))
|
||||
(build-system gnu-build-system)
|
||||
(arguments
|
||||
'(#:phases
|
||||
(modify-phases %standard-phases
|
||||
(add-before 'configure 'bootstrap
|
||||
(lambda _
|
||||
(zero? (system* "autoreconf" "-vfi")))))))
|
||||
(inputs
|
||||
`(("libusb" ,libusb)
|
||||
("udev" ,eudev)))
|
||||
(native-inputs
|
||||
`(("autoconf" ,autoconf)
|
||||
("automake" ,automake)
|
||||
("libtool" ,libtool)
|
||||
("pkg-config" ,pkg-config)))
|
||||
(home-page "http://www.signal11.us/oss/hidapi/")
|
||||
(synopsis "HID API library")
|
||||
(description
|
||||
"HIDAPI is a library which allows an application to interface with USB and Bluetooth
|
||||
HID-Class devices.")
|
||||
;; HIDAPI can be used under one of three licenses.
|
||||
(license (list gpl3
|
||||
bsd-3
|
||||
non-copyleft "file://LICENSE-orig.txt"))))
|
||||
|
|
|
@ -71,6 +71,8 @@ (define-module (gnu packages linux)
|
|||
#:use-module (gnu packages texinfo)
|
||||
#:use-module (gnu packages tls)
|
||||
#:use-module (gnu packages xml)
|
||||
#:use-module (gnu packages xdisorg)
|
||||
#:use-module (gnu packages xorg)
|
||||
#:use-module (guix build-system cmake)
|
||||
#:use-module (guix build-system gnu)
|
||||
#:use-module (guix build-system python)
|
||||
|
@ -323,14 +325,14 @@ (define* (make-linux-libre version hash supported-systems
|
|||
(define %intel-compatible-systems '("x86_64-linux" "i686-linux"))
|
||||
|
||||
(define-public linux-libre
|
||||
(make-linux-libre "4.8.4"
|
||||
"06fb2b1y7w0ixq4savn3hddp326mmzmg3400dpr8lyg919bwck3x"
|
||||
(make-linux-libre "4.8.5"
|
||||
"124sf2jvckn0afy1zfyaqgr1679qsx3fnylw1wpl7p5298hwyf9m"
|
||||
%intel-compatible-systems
|
||||
#:configuration-file kernel-config))
|
||||
|
||||
(define-public linux-libre-4.4
|
||||
(make-linux-libre "4.4.27"
|
||||
"07g0y8zbspw8d65386llcsnqlbv2s24dxvvbwm9kwm87rk3vin1r"
|
||||
(make-linux-libre "4.4.28"
|
||||
"1yn74vci0bygn5bi9mcgx1zz8xw9m3jb6j260wqsgkv1hbksa2yp"
|
||||
%intel-compatible-systems
|
||||
#:configuration-file kernel-config))
|
||||
|
||||
|
@ -341,8 +343,8 @@ (define-public linux-libre-4.1
|
|||
#:configuration-file kernel-config))
|
||||
|
||||
;; Avoid rebuilding kernel variants when there is a minor version bump.
|
||||
(define %linux-libre-version "4.8.4")
|
||||
(define %linux-libre-hash "06fb2b1y7w0ixq4savn3hddp326mmzmg3400dpr8lyg919bwck3x")
|
||||
(define %linux-libre-version "4.8.5")
|
||||
(define %linux-libre-hash "124sf2jvckn0afy1zfyaqgr1679qsx3fnylw1wpl7p5298hwyf9m")
|
||||
|
||||
(define-public linux-libre-arm-generic
|
||||
(make-linux-libre %linux-libre-version
|
||||
|
@ -3095,3 +3097,44 @@ (define-public libseccomp
|
|||
developers.")
|
||||
(home-page "https://github.com/seccomp/libseccomp")
|
||||
(license license:lgpl2.1)))
|
||||
|
||||
(define-public radeontop
|
||||
(package
|
||||
(name "radeontop")
|
||||
(version "0.9")
|
||||
(home-page "https://github.com/clbr/radeontop/")
|
||||
(source (origin
|
||||
(method url-fetch)
|
||||
(uri (string-append home-page "/archive/v" version ".tar.gz"))
|
||||
(file-name (string-append name "-" version ".tar.gz"))
|
||||
(sha256
|
||||
(base32
|
||||
"07fnimn6wwablmdjw0av11hk9a6xilbryh09izq4b2ic4b8md2p7"))))
|
||||
(build-system gnu-build-system)
|
||||
(arguments
|
||||
`(#:phases (modify-phases %standard-phases
|
||||
;; getver.sh uses ‘git --describe’, isn't worth an extra git
|
||||
;; dependency, and doesn't even work on release(!) tarballs.
|
||||
(add-after 'unpack 'report-correct-version
|
||||
(lambda _ (substitute* "getver.sh"
|
||||
(("ver=unknown")
|
||||
(string-append "ver=" ,version)))))
|
||||
(delete 'configure)) ; no configure script
|
||||
#:make-flags (list "CC=gcc"
|
||||
(string-append "PREFIX=" %output))
|
||||
#:tests? #f)) ; no tests
|
||||
(native-inputs
|
||||
`(("gnu-gettext" ,gnu-gettext)
|
||||
("pkg-config" ,pkg-config)))
|
||||
(inputs
|
||||
`(("libdrm" ,libdrm)
|
||||
("libpciaccess" ,libpciaccess)
|
||||
("ncurses" ,ncurses)))
|
||||
(synopsis "Usage monitor for AMD Radeon graphics")
|
||||
(description "RadeonTop monitors resource consumption on supported AMD
|
||||
Radeon Graphics Processing Units (GPUs), either in real time as bar graphs on
|
||||
a terminal or saved to a file for further processing. It measures both the
|
||||
activity of the GPU as a whole, which is also accurate during OpenCL
|
||||
computations, as well as separate component statistics that are only meaningful
|
||||
under OpenGL graphics workloads.")
|
||||
(license license:gpl3)))
|
||||
|
|
|
@ -311,7 +311,7 @@ (define-public bogofilter
|
|||
(define-public offlineimap
|
||||
(package
|
||||
(name "offlineimap")
|
||||
(version "7.0.8")
|
||||
(version "7.0.9")
|
||||
(source (origin
|
||||
(method url-fetch)
|
||||
(uri (string-append "https://github.com/OfflineIMAP/offlineimap/"
|
||||
|
@ -319,7 +319,7 @@ (define-public offlineimap
|
|||
(file-name (string-append name "-" version ".tar.gz"))
|
||||
(sha256
|
||||
(base32
|
||||
"0smxh5ag3cbn92kp49jq950j5m2pivs9kr04prpd1lw62hy7gnhr"))))
|
||||
"04kapx0ddz7ccwhcjshkml2y916wcan3rl28mpmq25p4gywlkhxf"))))
|
||||
(build-system python-build-system)
|
||||
(native-inputs
|
||||
`(("asciidoc" ,asciidoc)
|
||||
|
|
|
@ -1225,7 +1225,7 @@ (define-public slepc-complex-openmpi
|
|||
(define-public mumps
|
||||
(package
|
||||
(name "mumps")
|
||||
(version "5.0.1")
|
||||
(version "5.0.2")
|
||||
(source
|
||||
(origin
|
||||
(method url-fetch)
|
||||
|
@ -1233,7 +1233,7 @@ (define-public mumps
|
|||
version ".tar.gz"))
|
||||
(sha256
|
||||
(base32
|
||||
"1820jfp3mbl7n85765v5mp6p0gzqpgr4d2lrnhwj4gl7cwp5ndah"))
|
||||
"0igyc1pfzxdhpbad3v3lb86ixkdbqa1a8gbs15b04r2294h2nabp"))
|
||||
(patches (search-patches "mumps-build-parallelism.patch"))))
|
||||
(build-system gnu-build-system)
|
||||
(inputs
|
||||
|
@ -1250,8 +1250,7 @@ (define-public mumps
|
|||
,@%gnu-build-system-modules)
|
||||
#:phases
|
||||
(modify-phases %standard-phases
|
||||
(replace
|
||||
'configure
|
||||
(replace 'configure
|
||||
(lambda* (#:key inputs #:allow-other-keys)
|
||||
(call-with-output-file "Makefile.inc"
|
||||
(lambda (port)
|
||||
|
@ -1312,15 +1311,13 @@ (define-public mumps
|
|||
`((,ptscotch
|
||||
"-lptesmumps -lptscotch -lptscotcherr "
|
||||
"-Dptscotch")))))))))
|
||||
(replace
|
||||
'build
|
||||
(replace 'build
|
||||
;; By default only the d-precision library is built. Make with "all"
|
||||
;; target so that all precision libraries and examples are built.
|
||||
(lambda _
|
||||
(zero? (system* "make" "all"
|
||||
(format #f "-j~a" (parallel-job-count))))))
|
||||
(replace
|
||||
'check
|
||||
(replace 'check
|
||||
;; Run the simple test drivers, which read test input from stdin:
|
||||
;; from the "real" input for the single- and double-precision
|
||||
;; testers, and from the "cmplx" input for complex-precision
|
||||
|
@ -1343,15 +1340,15 @@ (define-public mumps
|
|||
(zero? (close-pipe tester)))))
|
||||
'("s" "d" "c" "z")
|
||||
'("real" "real" "cmplx" "cmplx")))))
|
||||
(replace
|
||||
'install
|
||||
(lambda* (#:key outputs #:allow-other-keys)
|
||||
(let ((out (assoc-ref outputs "out")))
|
||||
(copy-recursively "lib" (string-append out "/lib"))
|
||||
(copy-recursively "include" (string-append out "/include"))
|
||||
(when (file-exists? "libseq/libmpiseq.a")
|
||||
(copy-file "libseq/libmpiseq.a"
|
||||
(string-append out "/lib/libmpiseq.a")))))))))
|
||||
(replace 'install
|
||||
(lambda* (#:key outputs #:allow-other-keys)
|
||||
(let* ((out (assoc-ref outputs "out"))
|
||||
(libdir (string-append out "/lib")))
|
||||
(copy-recursively "lib" libdir)
|
||||
(copy-recursively "include" (string-append out "/include"))
|
||||
(when (file-exists? "libseq/libmpiseq.a")
|
||||
(install-file "libseq/libmpiseq.a" libdir))
|
||||
#t))))))
|
||||
(home-page "http://mumps.enseeiht.fr")
|
||||
(synopsis "Multifrontal sparse direct solver")
|
||||
(description
|
||||
|
|
|
@ -1772,9 +1772,9 @@ (define-public python-musicbrainzngs
|
|||
(define-public python2-musicbrainzngs
|
||||
(package-with-python2 python-musicbrainzngs))
|
||||
|
||||
(define-public python-pyechonest
|
||||
(define-public python2-pyechonest
|
||||
(package
|
||||
(name "python-pyechonest")
|
||||
(name "python2-pyechonest")
|
||||
(version "9.0.0")
|
||||
(source (origin
|
||||
(method url-fetch)
|
||||
|
@ -1783,6 +1783,11 @@ (define-public python-pyechonest
|
|||
(base32
|
||||
"1584nira3rkiman9dm81kdshihmkj21s8navndz2l8spnjwb790x"))))
|
||||
(build-system python-build-system)
|
||||
(arguments
|
||||
`(;; Python 3 is not supported:
|
||||
;; https://github.com/echonest/pyechonest/issues/42
|
||||
#:python ,python-2))
|
||||
(native-inputs `(("python2-setuptools" ,python2-setuptools)))
|
||||
(home-page "https://github.com/echonest/pyechonest")
|
||||
(synopsis "Python interface to The Echo Nest APIs")
|
||||
(description "Pyechonest is a Python library for the Echo Nest API. With
|
||||
|
@ -1799,13 +1804,7 @@ (define-public python-pyechonest
|
|||
about the track including key, duration, mode, tempo, time signature along with
|
||||
detailed track info including timbre, pitch, rhythm and loudness information.
|
||||
@end enumerate\n")
|
||||
(license license:bsd-3)
|
||||
(properties `((python2-variant . ,(delay python2-pyechonest))))))
|
||||
|
||||
(define-public python2-pyechonest
|
||||
(package (inherit (package-with-python2
|
||||
(strip-python2-variant python-pyechonest)))
|
||||
(native-inputs `(("python2-setuptools" ,python2-setuptools)))))
|
||||
(license license:bsd-3)))
|
||||
|
||||
(define-public python-pylast
|
||||
(package
|
||||
|
|
843
gnu/packages/patches/openocd-nrf52.patch
Normal file
843
gnu/packages/patches/openocd-nrf52.patch
Normal file
|
@ -0,0 +1,843 @@
|
|||
This patch adds support for nRF52 series devices. It is patchset 7 from
|
||||
<http://openocd.zylin.com/#/c/3511/>, which has been tested, but not
|
||||
merged yet in master.
|
||||
|
||||
From: Michael Dietz <mjdietzx@gmail.com>
|
||||
Date: Mon, 30 May 2016 12:50:44 +0000 (-0700)
|
||||
Subject: Added support for nRF52 Series Devices.
|
||||
X-Git-Url: http://openocd.zylin.com/gitweb?p=openocd.git;a=commitdiff_plain;h=9ba15633e221d9d72e320372ba8f49d3f30d4bce
|
||||
|
||||
Added support for nRF52 Series Devices.
|
||||
|
||||
Both nrf52.c and nrf52.cfg are based off of previous nRF51 files.
|
||||
- Some possible race conditions with NVMC have been fixed in nRF52.c
|
||||
- Removed nrf51_get_probed_chip_if_halted() as the core does not have to be halted to perform operations where it is called.
|
||||
- Only registers that are needed by openOCD are defined, some registers in nRF51 don't exist in nRF52 and are removed.
|
||||
- Some all around cleanup has been done.
|
||||
- The protection mechanism is completely different on nRF52 and this has not been implemented yet - just prints a warning and returns for now.
|
||||
|
||||
Change-Id: I4dd42c86f33f450709bb981806c2655f04aa6201
|
||||
Signed-off-by: Michael Dietz <mjdietzx@gmail.com>
|
||||
---
|
||||
|
||||
diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am
|
||||
index c167e8f..b6a2be3 100644
|
||||
--- a/src/flash/nor/Makefile.am
|
||||
+++ b/src/flash/nor/Makefile.am
|
||||
@@ -37,6 +37,7 @@ NOR_DRIVERS = \
|
||||
niietcm4.c \
|
||||
non_cfi.c \
|
||||
nrf51.c \
|
||||
+ nrf52.c \
|
||||
numicro.c \
|
||||
ocl.c \
|
||||
pic32mx.c \
|
||||
diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c
|
||||
index 56a5cb2..3e071bd 100644
|
||||
--- a/src/flash/nor/drivers.c
|
||||
+++ b/src/flash/nor/drivers.c
|
||||
@@ -48,6 +48,7 @@ extern struct flash_driver mdr_flash;
|
||||
extern struct flash_driver mrvlqspi_flash;
|
||||
extern struct flash_driver niietcm4_flash;
|
||||
extern struct flash_driver nrf51_flash;
|
||||
+extern struct flash_driver nrf52_flash;
|
||||
extern struct flash_driver numicro_flash;
|
||||
extern struct flash_driver ocl_flash;
|
||||
extern struct flash_driver pic32mx_flash;
|
||||
@@ -100,6 +101,7 @@ static struct flash_driver *flash_drivers[] = {
|
||||
&mrvlqspi_flash,
|
||||
&niietcm4_flash,
|
||||
&nrf51_flash,
|
||||
+ &nrf52_flash,
|
||||
&numicro_flash,
|
||||
&ocl_flash,
|
||||
&pic32mx_flash,
|
||||
diff --git a/src/flash/nor/nrf52.c b/src/flash/nor/nrf52.c
|
||||
new file mode 100644
|
||||
index 0000000..7f2bd35
|
||||
--- /dev/null
|
||||
+++ b/src/flash/nor/nrf52.c
|
||||
@@ -0,0 +1,733 @@
|
||||
+/***************************************************************************
|
||||
+ * Copyright (C) 2013 Synapse Product Development *
|
||||
+ * Andrey Smirnov <andrew.smironv@gmail.com> *
|
||||
+ * Angus Gratton <gus@projectgus.com> *
|
||||
+ * Erdem U. Altunyurt <spamjunkeater@gmail.com> *
|
||||
+ * *
|
||||
+ * This program is free software; you can redistribute it and/or modify *
|
||||
+ * it under the terms of the GNU General Public License as published by *
|
||||
+ * the Free Software Foundation; either version 2 of the License, or *
|
||||
+ * (at your option) any later version. *
|
||||
+ * *
|
||||
+ * This program is distributed in the hope that it will be useful, *
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
+ * GNU General Public License for more details. *
|
||||
+ * *
|
||||
+ * You should have received a copy of the GNU General Public License *
|
||||
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
+ ***************************************************************************/
|
||||
+
|
||||
+#ifdef HAVE_CONFIG_H
|
||||
+#include "config.h"
|
||||
+#endif
|
||||
+
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
+#include "imp.h"
|
||||
+#include <target/algorithm.h>
|
||||
+#include <target/armv7m.h>
|
||||
+#include <helper/types.h>
|
||||
+
|
||||
+/* nRF52 Register addresses used by openOCD. */
|
||||
+#define NRF52_FLASH_BASE_ADDR (0x0)
|
||||
+
|
||||
+#define NRF52_FICR_BASE_ADDR (0x10000000)
|
||||
+#define NRF52_FICR_CODEPAGESIZE_ADDR (NRF52_FICR_BASE_ADDR | 0x010)
|
||||
+#define NRF52_FICR_CODESIZE_ADDR (NRF52_FICR_BASE_ADDR | 0x014)
|
||||
+
|
||||
+#define NRF52_UICR_BASE_ADDR (0x10001000)
|
||||
+
|
||||
+#define NRF52_NVMC_BASE_ADDR (0x4001E000)
|
||||
+#define NRF52_NVMC_READY_ADDR (NRF52_NVMC_BASE_ADDR | 0x400)
|
||||
+#define NRF52_NVMC_CONFIG_ADDR (NRF52_NVMC_BASE_ADDR | 0x504)
|
||||
+#define NRF52_NVMC_ERASEPAGE_ADDR (NRF52_NVMC_BASE_ADDR | 0x508)
|
||||
+#define NRF52_NVMC_ERASEALL_ADDR (NRF52_NVMC_BASE_ADDR | 0x50C)
|
||||
+#define NRF52_NVMC_ERASEUICR_ADDR (NRF52_NVMC_BASE_ADDR | 0x514)
|
||||
+
|
||||
+/* nRF52 bit fields. */
|
||||
+enum nrf52_nvmc_config_bits {
|
||||
+ NRF52_NVMC_CONFIG_REN = 0x0,
|
||||
+ NRF52_NVMC_CONFIG_WEN = 0x01,
|
||||
+ NRF52_NVMC_CONFIG_EEN = 0x02
|
||||
+};
|
||||
+
|
||||
+enum nrf52_nvmc_ready_bits {
|
||||
+ NRF52_NVMC_BUSY = 0x0,
|
||||
+ NRF52_NVMC_READY = 0x01
|
||||
+};
|
||||
+
|
||||
+/* nRF52 state information. */
|
||||
+struct nrf52_info {
|
||||
+ uint32_t code_page_size; /* Size of FLASH page in bytes. */
|
||||
+ uint32_t code_memory_size; /* Size of Code FLASH region in bytes. */
|
||||
+
|
||||
+ struct {
|
||||
+ bool probed;
|
||||
+ int (*write) (struct flash_bank *bank,
|
||||
+ struct nrf52_info *chip,
|
||||
+ const uint8_t *buffer, uint32_t offset, uint32_t count);
|
||||
+ } bank[2]; /* There are two regions in nRF52 FLASH - Code and UICR. */
|
||||
+ struct target *target;
|
||||
+};
|
||||
+
|
||||
+static int nrf52_protect_check(struct flash_bank *bank);
|
||||
+
|
||||
+static int nrf52_probe(struct flash_bank *bank)
|
||||
+{
|
||||
+ int res;
|
||||
+ struct nrf52_info *chip = bank->driver_priv;
|
||||
+ assert(chip != NULL);
|
||||
+
|
||||
+ res = target_read_u32(chip->target,
|
||||
+ NRF52_FICR_CODEPAGESIZE_ADDR,
|
||||
+ &chip->code_page_size);
|
||||
+ if (res != ERROR_OK) {
|
||||
+ LOG_ERROR("Couldn't read code page size");
|
||||
+ return res;
|
||||
+ }
|
||||
+
|
||||
+ res = target_read_u32(chip->target,
|
||||
+ NRF52_FICR_CODESIZE_ADDR,
|
||||
+ &chip->code_memory_size);
|
||||
+ if (res != ERROR_OK) {
|
||||
+ LOG_ERROR("Couldn't read code memory size");
|
||||
+ return res;
|
||||
+ }
|
||||
+
|
||||
+ chip->code_memory_size = chip->code_memory_size * chip->code_page_size;
|
||||
+
|
||||
+ if (bank->base == NRF52_FLASH_BASE_ADDR) {
|
||||
+ bank->size = chip->code_memory_size;
|
||||
+ bank->num_sectors = bank->size / chip->code_page_size;
|
||||
+ bank->sectors = calloc(bank->num_sectors,
|
||||
+ sizeof((bank->sectors)[0]));
|
||||
+ if (!bank->sectors)
|
||||
+ return ERROR_FLASH_BANK_NOT_PROBED;
|
||||
+
|
||||
+ /* Fill out the sector information: All nRF51 sectors are the same size. */
|
||||
+ for (int i = 0; i < bank->num_sectors; i++) {
|
||||
+ bank->sectors[i].size = chip->code_page_size;
|
||||
+ bank->sectors[i].offset = i * chip->code_page_size;
|
||||
+
|
||||
+ /* Mark as unknown. */
|
||||
+ bank->sectors[i].is_erased = -1;
|
||||
+ bank->sectors[i].is_protected = -1;
|
||||
+ }
|
||||
+
|
||||
+ nrf52_protect_check(bank);
|
||||
+
|
||||
+ chip->bank[0].probed = true;
|
||||
+ } else { /* This is the UICR bank. */
|
||||
+ bank->size = chip->code_page_size;
|
||||
+ bank->num_sectors = 1;
|
||||
+ bank->sectors = calloc(bank->num_sectors,
|
||||
+ sizeof((bank->sectors)[0]));
|
||||
+ if (!bank->sectors)
|
||||
+ return ERROR_FLASH_BANK_NOT_PROBED;
|
||||
+
|
||||
+ bank->sectors[0].size = bank->size;
|
||||
+ bank->sectors[0].offset = 0;
|
||||
+
|
||||
+ bank->sectors[0].is_erased = -1;
|
||||
+ bank->sectors[0].is_protected = -1;
|
||||
+
|
||||
+ chip->bank[1].probed = true;
|
||||
+ }
|
||||
+
|
||||
+ return ERROR_OK;
|
||||
+}
|
||||
+
|
||||
+static int nrf52_bank_is_probed(struct flash_bank *bank)
|
||||
+{
|
||||
+ struct nrf52_info *chip = bank->driver_priv;
|
||||
+ assert(chip != NULL);
|
||||
+
|
||||
+ return chip->bank[bank->bank_number].probed;
|
||||
+}
|
||||
+
|
||||
+static int nrf52_auto_probe(struct flash_bank *bank)
|
||||
+{
|
||||
+ if (!nrf52_bank_is_probed(bank))
|
||||
+ return nrf52_probe(bank);
|
||||
+ else
|
||||
+ return ERROR_OK;
|
||||
+}
|
||||
+
|
||||
+static int nrf52_wait_for_nvmc(struct nrf52_info *chip)
|
||||
+{
|
||||
+ int res;
|
||||
+ uint32_t ready;
|
||||
+ int timeout = 100;
|
||||
+
|
||||
+ do {
|
||||
+ res = target_read_u32(chip->target, NRF52_NVMC_READY_ADDR, &ready);
|
||||
+ if (res != ERROR_OK) {
|
||||
+ LOG_ERROR("Couldn't read NVMC_READY register");
|
||||
+ return res;
|
||||
+ }
|
||||
+
|
||||
+ if (ready == NRF52_NVMC_READY)
|
||||
+ return ERROR_OK;
|
||||
+
|
||||
+ alive_sleep(1);
|
||||
+ } while (timeout--);
|
||||
+
|
||||
+ LOG_DEBUG("Timed out waiting for the NVMC to be ready");
|
||||
+ return ERROR_FLASH_BUSY;
|
||||
+}
|
||||
+
|
||||
+static int nrf52_nvmc_erase_enable(struct nrf52_info *chip)
|
||||
+{
|
||||
+ int res;
|
||||
+
|
||||
+ res = nrf52_wait_for_nvmc(chip);
|
||||
+ if (res != ERROR_OK)
|
||||
+ return res;
|
||||
+
|
||||
+ res = target_write_u32(chip->target,
|
||||
+ NRF52_NVMC_CONFIG_ADDR,
|
||||
+ NRF52_NVMC_CONFIG_EEN);
|
||||
+ if (res != ERROR_OK) {
|
||||
+ LOG_ERROR("Failed to configure the NVMC for erasing");
|
||||
+ return res;
|
||||
+ }
|
||||
+
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
+static int nrf52_nvmc_write_enable(struct nrf52_info *chip)
|
||||
+{
|
||||
+ int res;
|
||||
+
|
||||
+ res = nrf52_wait_for_nvmc(chip);
|
||||
+ if (res != ERROR_OK)
|
||||
+ return res;
|
||||
+
|
||||
+ res = target_write_u32(chip->target,
|
||||
+ NRF52_NVMC_CONFIG_ADDR,
|
||||
+ NRF52_NVMC_CONFIG_WEN);
|
||||
+ if (res != ERROR_OK) {
|
||||
+ LOG_ERROR("Failed to configure the NVMC for writing");
|
||||
+ return res;
|
||||
+ }
|
||||
+
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
+static int nrf52_nvmc_read_only(struct nrf52_info *chip)
|
||||
+{
|
||||
+ int res;
|
||||
+
|
||||
+ res = nrf52_wait_for_nvmc(chip);
|
||||
+ if (res != ERROR_OK)
|
||||
+ return res;
|
||||
+
|
||||
+ res = target_write_u32(chip->target,
|
||||
+ NRF52_NVMC_CONFIG_ADDR,
|
||||
+ NRF52_NVMC_CONFIG_REN);
|
||||
+ if (res != ERROR_OK) {
|
||||
+ LOG_ERROR("Failed to configure the NVMC for read-only");
|
||||
+ return res;
|
||||
+ }
|
||||
+
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
+static int nrf52_nvmc_generic_erase(struct nrf52_info *chip,
|
||||
+ uint32_t erase_register,
|
||||
+ uint32_t erase_value)
|
||||
+{
|
||||
+ int res;
|
||||
+
|
||||
+ res = nrf52_nvmc_erase_enable(chip);
|
||||
+ if (res != ERROR_OK)
|
||||
+ return res;
|
||||
+
|
||||
+ res = target_write_u32(chip->target,
|
||||
+ erase_register,
|
||||
+ erase_value);
|
||||
+ if (res != ERROR_OK)
|
||||
+ LOG_ERROR("Failed to write NVMC erase register");
|
||||
+
|
||||
+ return nrf52_nvmc_read_only(chip);
|
||||
+}
|
||||
+
|
||||
+static int nrf52_protect_check(struct flash_bank *bank)
|
||||
+{
|
||||
+ LOG_WARNING("nrf52_protect_check() is not implemented for nRF52 series devices yet");
|
||||
+ return ERROR_OK;
|
||||
+}
|
||||
+
|
||||
+static int nrf52_protect(struct flash_bank *bank, int set, int first, int last)
|
||||
+{
|
||||
+ LOG_WARNING("nrf52_protect() is not implemented for nRF52 series devices yet");
|
||||
+ return ERROR_OK;
|
||||
+}
|
||||
+
|
||||
+static struct flash_sector *nrf52_find_sector_by_address(struct flash_bank *bank, uint32_t address)
|
||||
+{
|
||||
+ struct nrf52_info *chip = bank->driver_priv;
|
||||
+ assert(chip != NULL);
|
||||
+
|
||||
+ for (int i = 0; i < bank->num_sectors; i++)
|
||||
+ if (bank->sectors[i].offset <= address &&
|
||||
+ address < (bank->sectors[i].offset + chip->code_page_size)) {
|
||||
+ return &bank->sectors[i];
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static int nrf52_erase_all(struct nrf52_info *chip)
|
||||
+{
|
||||
+ LOG_DEBUG("Erasing all non-volatile memory");
|
||||
+ return nrf52_nvmc_generic_erase(chip,
|
||||
+ NRF52_NVMC_ERASEALL_ADDR,
|
||||
+ 0x01);
|
||||
+}
|
||||
+
|
||||
+static int nrf52_erase_page(struct flash_bank *bank,
|
||||
+ struct nrf52_info *chip,
|
||||
+ struct flash_sector *sector)
|
||||
+{
|
||||
+ int res;
|
||||
+
|
||||
+ LOG_DEBUG("Erasing page at 0x%"PRIx32, sector->offset);
|
||||
+ if (sector->is_protected == 1) {
|
||||
+ LOG_ERROR("Cannot erase protected sector at 0x%" PRIx32, sector->offset);
|
||||
+ return ERROR_FAIL;
|
||||
+ }
|
||||
+
|
||||
+ if (bank->base == NRF52_UICR_BASE_ADDR) {
|
||||
+ res = nrf52_nvmc_generic_erase(chip,
|
||||
+ NRF52_NVMC_ERASEUICR_ADDR,
|
||||
+ 0x00000001);
|
||||
+ } else {
|
||||
+ res = nrf52_nvmc_generic_erase(chip,
|
||||
+ NRF52_NVMC_ERASEPAGE_ADDR,
|
||||
+ sector->offset);
|
||||
+ }
|
||||
+
|
||||
+ if (res == ERROR_OK)
|
||||
+ sector->is_erased = 1;
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
+static const uint8_t nrf52_flash_write_code[] = {
|
||||
+ /* See contrib/loaders/flash/cortex-m0.S */
|
||||
+ /* <wait_fifo>: */
|
||||
+ 0x0d, 0x68, /* ldr r5, [r1, #0] */
|
||||
+ 0x00, 0x2d, /* cmp r5, #0 */
|
||||
+ 0x0b, 0xd0, /* beq.n 1e <exit> */
|
||||
+ 0x4c, 0x68, /* ldr r4, [r1, #4] */
|
||||
+ 0xac, 0x42, /* cmp r4, r5 */
|
||||
+ 0xf9, 0xd0, /* beq.n 0 <wait_fifo> */
|
||||
+ 0x20, 0xcc, /* ldmia r4!, {r5} */
|
||||
+ 0x20, 0xc3, /* stmia r3!, {r5} */
|
||||
+ 0x94, 0x42, /* cmp r4, r2 */
|
||||
+ 0x01, 0xd3, /* bcc.n 18 <no_wrap> */
|
||||
+ 0x0c, 0x46, /* mov r4, r1 */
|
||||
+ 0x08, 0x34, /* adds r4, #8 */
|
||||
+ /* <no_wrap>: */
|
||||
+ 0x4c, 0x60, /* str r4, [r1, #4] */
|
||||
+ 0x04, 0x38, /* subs r0, #4 */
|
||||
+ 0xf0, 0xd1, /* bne.n 0 <wait_fifo> */
|
||||
+ /* <exit>: */
|
||||
+ 0x00, 0xbe /* bkpt 0x0000 */
|
||||
+};
|
||||
+
|
||||
+
|
||||
+/* Start a low level flash write for the specified region */
|
||||
+static int nrf52_ll_flash_write(struct nrf52_info *chip, uint32_t offset, const uint8_t *buffer, uint32_t bytes)
|
||||
+{
|
||||
+ struct target *target = chip->target;
|
||||
+ uint32_t buffer_size = 8192;
|
||||
+ struct working_area *write_algorithm;
|
||||
+ struct working_area *source;
|
||||
+ uint32_t address = NRF52_FLASH_BASE_ADDR + offset;
|
||||
+ struct reg_param reg_params[4];
|
||||
+ struct armv7m_algorithm armv7m_info;
|
||||
+ int retval = ERROR_OK;
|
||||
+
|
||||
+ LOG_DEBUG("Writing buffer to flash offset=0x%"PRIx32" bytes=0x%"PRIx32, offset, bytes);
|
||||
+ assert(bytes % 4 == 0);
|
||||
+
|
||||
+ /* allocate working area with flash programming code */
|
||||
+ if (target_alloc_working_area(target, sizeof(nrf52_flash_write_code),
|
||||
+ &write_algorithm) != ERROR_OK) {
|
||||
+ LOG_WARNING("no working area available, falling back to slow memory writes");
|
||||
+
|
||||
+ for (; bytes > 0; bytes -= 4) {
|
||||
+ retval = target_write_memory(chip->target,
|
||||
+ offset, 4, 1, buffer);
|
||||
+ if (retval != ERROR_OK)
|
||||
+ return retval;
|
||||
+
|
||||
+ retval = nrf52_wait_for_nvmc(chip);
|
||||
+ if (retval != ERROR_OK)
|
||||
+ return retval;
|
||||
+
|
||||
+ offset += 4;
|
||||
+ buffer += 4;
|
||||
+ }
|
||||
+
|
||||
+ return ERROR_OK;
|
||||
+ }
|
||||
+
|
||||
+ LOG_WARNING("using fast async flash loader. This is currently supported");
|
||||
+ LOG_WARNING("only with ST-Link and CMSIS-DAP. If you have issues, add");
|
||||
+ LOG_WARNING("\"set WORKAREASIZE 0\" before sourcing nrf52.cfg to disable it");
|
||||
+
|
||||
+ retval = target_write_buffer(target, write_algorithm->address,
|
||||
+ sizeof(nrf52_flash_write_code),
|
||||
+ nrf52_flash_write_code);
|
||||
+ if (retval != ERROR_OK)
|
||||
+ return retval;
|
||||
+
|
||||
+ /* memory buffer */
|
||||
+ while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) {
|
||||
+ buffer_size /= 2;
|
||||
+ buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */
|
||||
+ if (buffer_size <= 256) {
|
||||
+ /* free working area, write algorithm already allocated */
|
||||
+ target_free_working_area(target, write_algorithm);
|
||||
+
|
||||
+ LOG_WARNING("No large enough working area available, can't do block memory writes");
|
||||
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
|
||||
+ armv7m_info.core_mode = ARM_MODE_THREAD;
|
||||
+
|
||||
+ init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* byte count */
|
||||
+ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* buffer start */
|
||||
+ init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* buffer end */
|
||||
+ init_reg_param(®_params[3], "r3", 32, PARAM_IN_OUT); /* target address */
|
||||
+
|
||||
+ buf_set_u32(reg_params[0].value, 0, 32, bytes);
|
||||
+ buf_set_u32(reg_params[1].value, 0, 32, source->address);
|
||||
+ buf_set_u32(reg_params[2].value, 0, 32, source->address + source->size);
|
||||
+ buf_set_u32(reg_params[3].value, 0, 32, address);
|
||||
+
|
||||
+ retval = target_run_flash_async_algorithm(target, buffer, bytes/4, 4,
|
||||
+ 0, NULL,
|
||||
+ 4, reg_params,
|
||||
+ source->address, source->size,
|
||||
+ write_algorithm->address, 0,
|
||||
+ &armv7m_info);
|
||||
+
|
||||
+ target_free_working_area(target, source);
|
||||
+ target_free_working_area(target, write_algorithm);
|
||||
+
|
||||
+ destroy_reg_param(®_params[0]);
|
||||
+ destroy_reg_param(®_params[1]);
|
||||
+ destroy_reg_param(®_params[2]);
|
||||
+ destroy_reg_param(®_params[3]);
|
||||
+
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
+/* Check and erase flash sectors in specified range, then start a low level page write.
|
||||
+ start/end must be sector aligned.
|
||||
+*/
|
||||
+static int nrf52_write_pages(struct flash_bank *bank, uint32_t start, uint32_t end, const uint8_t *buffer)
|
||||
+{
|
||||
+ int res;
|
||||
+ uint32_t offset;
|
||||
+ struct flash_sector *sector;
|
||||
+ struct nrf52_info *chip = bank->driver_priv;
|
||||
+ assert(chip != NULL);
|
||||
+
|
||||
+ assert(start % chip->code_page_size == 0);
|
||||
+ assert(end % chip->code_page_size == 0);
|
||||
+
|
||||
+ /* Erase all sectors */
|
||||
+ for (offset = start; offset < end; offset += chip->code_page_size) {
|
||||
+ sector = nrf52_find_sector_by_address(bank, offset);
|
||||
+
|
||||
+ if (sector == NULL) {
|
||||
+ LOG_ERROR("Invalid sector @ 0x%08"PRIx32, offset);
|
||||
+ return ERROR_FLASH_SECTOR_INVALID;
|
||||
+ }
|
||||
+
|
||||
+ if (sector->is_protected == 1) {
|
||||
+ LOG_ERROR("Can't erase protected sector @ 0x%08"PRIx32, offset);
|
||||
+ return ERROR_FAIL;
|
||||
+ }
|
||||
+
|
||||
+ if (sector->is_erased != 1) { /* 1 = erased, 0= not erased, -1 = unknown */
|
||||
+ res = nrf52_erase_page(bank, chip, sector);
|
||||
+ if (res != ERROR_OK) {
|
||||
+ LOG_ERROR("Failed to erase sector @ 0x%08"PRIx32, sector->offset);
|
||||
+ return res;
|
||||
+ }
|
||||
+ }
|
||||
+ sector->is_erased = 1;
|
||||
+ }
|
||||
+
|
||||
+ res = nrf52_nvmc_write_enable(chip);
|
||||
+ if (res != ERROR_OK)
|
||||
+ return res;
|
||||
+
|
||||
+ res = nrf52_ll_flash_write(chip, start, buffer, (end - start));
|
||||
+ if (res != ERROR_OK) {
|
||||
+ LOG_ERROR("Failed to write FLASH");
|
||||
+ nrf52_nvmc_read_only(chip);
|
||||
+ return res;
|
||||
+ }
|
||||
+
|
||||
+ return nrf52_nvmc_read_only(chip);
|
||||
+}
|
||||
+
|
||||
+static int nrf52_erase(struct flash_bank *bank, int first, int last)
|
||||
+{
|
||||
+ int res = ERROR_OK;
|
||||
+ struct nrf52_info *chip = bank->driver_priv;
|
||||
+ assert(chip != NULL);
|
||||
+
|
||||
+ /* For each sector to be erased */
|
||||
+ for (int s = first; s <= last && res == ERROR_OK; s++)
|
||||
+ res = nrf52_erase_page(bank, chip, &bank->sectors[s]);
|
||||
+
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
+static int nrf52_code_flash_write(struct flash_bank *bank,
|
||||
+ struct nrf52_info *chip,
|
||||
+ const uint8_t *buffer, uint32_t offset, uint32_t count)
|
||||
+{
|
||||
+ int res;
|
||||
+ /* Need to perform reads to fill any gaps we need to preserve in the first page,
|
||||
+ before the start of buffer, or in the last page, after the end of buffer */
|
||||
+ uint32_t first_page = offset / chip->code_page_size;
|
||||
+ uint32_t last_page = DIV_ROUND_UP(offset+count, chip->code_page_size);
|
||||
+
|
||||
+ uint32_t first_page_offset = first_page * chip->code_page_size;
|
||||
+ uint32_t last_page_offset = last_page * chip->code_page_size;
|
||||
+
|
||||
+ LOG_DEBUG("Padding write from 0x%08"PRIx32"-0x%08"PRIx32" as 0x%08"PRIx32"-0x%08"PRIx32,
|
||||
+ offset, offset+count, first_page_offset, last_page_offset);
|
||||
+
|
||||
+ uint32_t page_cnt = last_page - first_page;
|
||||
+ uint8_t buffer_to_flash[page_cnt * chip->code_page_size];
|
||||
+
|
||||
+ /* Fill in any space between start of first page and start of buffer */
|
||||
+ uint32_t pre = offset - first_page_offset;
|
||||
+ if (pre > 0) {
|
||||
+ res = target_read_memory(bank->target, first_page_offset, 1, pre, buffer_to_flash);
|
||||
+ if (res != ERROR_OK)
|
||||
+ return res;
|
||||
+ }
|
||||
+
|
||||
+ /* Fill in main contents of buffer */
|
||||
+ memcpy(buffer_to_flash + pre, buffer, count);
|
||||
+
|
||||
+ /* Fill in any space between end of buffer and end of last page */
|
||||
+ uint32_t post = last_page_offset - (offset + count);
|
||||
+ if (post > 0) {
|
||||
+ /* Retrieve the full row contents from Flash */
|
||||
+ res = target_read_memory(bank->target, offset + count, 1, post, buffer_to_flash + pre + count);
|
||||
+ if (res != ERROR_OK)
|
||||
+ return res;
|
||||
+ }
|
||||
+
|
||||
+ return nrf52_write_pages(bank, first_page_offset, last_page_offset, buffer_to_flash);
|
||||
+}
|
||||
+
|
||||
+static int nrf52_uicr_flash_write(struct flash_bank *bank,
|
||||
+ struct nrf52_info *chip,
|
||||
+ const uint8_t *buffer, uint32_t offset, uint32_t count)
|
||||
+{
|
||||
+ int res;
|
||||
+ uint32_t nrf52_uicr_size = chip->code_page_size;
|
||||
+ uint8_t uicr[nrf52_uicr_size];
|
||||
+ struct flash_sector *sector = &bank->sectors[0];
|
||||
+
|
||||
+ if ((offset + count) > nrf52_uicr_size)
|
||||
+ return ERROR_FAIL;
|
||||
+
|
||||
+ res = target_read_memory(bank->target, NRF52_UICR_BASE_ADDR, 1, nrf52_uicr_size, uicr);
|
||||
+
|
||||
+ if (res != ERROR_OK)
|
||||
+ return res;
|
||||
+
|
||||
+ if (sector->is_erased != 1) {
|
||||
+ res = nrf52_erase_page(bank, chip, sector);
|
||||
+ if (res != ERROR_OK)
|
||||
+ return res;
|
||||
+ }
|
||||
+
|
||||
+ memcpy(&uicr[offset], buffer, count);
|
||||
+
|
||||
+ res = nrf52_nvmc_write_enable(chip);
|
||||
+ if (res != ERROR_OK)
|
||||
+ return res;
|
||||
+
|
||||
+ res = nrf52_ll_flash_write(chip, NRF52_UICR_BASE_ADDR, uicr, nrf52_uicr_size);
|
||||
+ if (res != ERROR_OK) {
|
||||
+ nrf52_nvmc_read_only(chip);
|
||||
+ return res;
|
||||
+ }
|
||||
+
|
||||
+ return nrf52_nvmc_read_only(chip);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int nrf52_write(struct flash_bank *bank, const uint8_t *buffer,
|
||||
+ uint32_t offset, uint32_t count)
|
||||
+{
|
||||
+ struct nrf52_info *chip = bank->driver_priv;
|
||||
+ assert(chip != NULL);
|
||||
+
|
||||
+ return chip->bank[bank->bank_number].write(bank, chip, buffer, offset, count);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+FLASH_BANK_COMMAND_HANDLER(nrf52_flash_bank_command)
|
||||
+{
|
||||
+ static struct nrf52_info *chip;
|
||||
+
|
||||
+ assert(bank != NULL);
|
||||
+
|
||||
+ switch (bank->base) {
|
||||
+ case NRF52_FLASH_BASE_ADDR:
|
||||
+ bank->bank_number = 0;
|
||||
+ break;
|
||||
+ case NRF52_UICR_BASE_ADDR:
|
||||
+ bank->bank_number = 1;
|
||||
+ break;
|
||||
+ default:
|
||||
+ LOG_ERROR("Invalid bank address 0x%08" PRIx32, bank->base);
|
||||
+ return ERROR_FAIL;
|
||||
+ }
|
||||
+
|
||||
+ if (!chip) {
|
||||
+ /* Create a new chip */
|
||||
+ chip = calloc(1, sizeof(*chip));
|
||||
+ assert(chip != NULL);
|
||||
+
|
||||
+ chip->target = bank->target;
|
||||
+ }
|
||||
+
|
||||
+ switch (bank->base) {
|
||||
+ case NRF52_FLASH_BASE_ADDR:
|
||||
+ chip->bank[bank->bank_number].write = nrf52_code_flash_write;
|
||||
+ break;
|
||||
+ case NRF52_UICR_BASE_ADDR:
|
||||
+ chip->bank[bank->bank_number].write = nrf52_uicr_flash_write;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ chip->bank[bank->bank_number].probed = false;
|
||||
+ bank->driver_priv = chip;
|
||||
+
|
||||
+ return ERROR_OK;
|
||||
+}
|
||||
+
|
||||
+COMMAND_HANDLER(nrf52_handle_mass_erase_command)
|
||||
+{
|
||||
+ int res;
|
||||
+ struct flash_bank *bank = NULL;
|
||||
+ struct target *target = get_current_target(CMD_CTX);
|
||||
+
|
||||
+ res = get_flash_bank_by_addr(target, NRF52_FLASH_BASE_ADDR, true, &bank);
|
||||
+ if (res != ERROR_OK)
|
||||
+ return res;
|
||||
+
|
||||
+ assert(bank != NULL);
|
||||
+
|
||||
+ struct nrf52_info *chip = bank->driver_priv;
|
||||
+ assert(chip != NULL);
|
||||
+
|
||||
+ res = nrf52_erase_all(chip);
|
||||
+ if (res != ERROR_OK) {
|
||||
+ LOG_ERROR("Failed to erase the chip");
|
||||
+ nrf52_protect_check(bank);
|
||||
+ return res;
|
||||
+ }
|
||||
+
|
||||
+ for (int i = 0; i < bank->num_sectors; i++)
|
||||
+ bank->sectors[i].is_erased = 1;
|
||||
+
|
||||
+ res = nrf52_protect_check(bank);
|
||||
+ if (res != ERROR_OK) {
|
||||
+ LOG_ERROR("Failed to check chip's write protection");
|
||||
+ return res;
|
||||
+ }
|
||||
+
|
||||
+ res = get_flash_bank_by_addr(target, NRF52_UICR_BASE_ADDR, true, &bank);
|
||||
+ if (res != ERROR_OK)
|
||||
+ return res;
|
||||
+
|
||||
+ bank->sectors[0].is_erased = 1;
|
||||
+
|
||||
+ return ERROR_OK;
|
||||
+}
|
||||
+
|
||||
+static int nrf52_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||
+{
|
||||
+ int res;
|
||||
+ uint32_t ficr[2];
|
||||
+ struct nrf52_info *chip = bank->driver_priv;
|
||||
+ assert(chip != NULL);
|
||||
+
|
||||
+ res = target_read_u32(chip->target, NRF52_FICR_CODEPAGESIZE_ADDR, &ficr[0]);
|
||||
+ if (res != ERROR_OK) {
|
||||
+ LOG_ERROR("Couldn't read NVMC_READY register");
|
||||
+ return res;
|
||||
+ }
|
||||
+
|
||||
+ res = target_read_u32(chip->target, NRF52_FICR_CODESIZE_ADDR, &ficr[1]);
|
||||
+ if (res != ERROR_OK) {
|
||||
+ LOG_ERROR("Couldn't read NVMC_READY register");
|
||||
+ return res;
|
||||
+ }
|
||||
+
|
||||
+ snprintf(buf, buf_size,
|
||||
+ "\n--------nRF52 Series Device--------\n\n"
|
||||
+ "\n[factory information control block]\n"
|
||||
+ "code page size: %"PRIu32"B\n"
|
||||
+ "code memory size: %"PRIu32"kB\n",
|
||||
+ ficr[0],
|
||||
+ (ficr[1] * ficr[0]) / 1024);
|
||||
+
|
||||
+ return ERROR_OK;
|
||||
+}
|
||||
+
|
||||
+static const struct command_registration nrf52_exec_command_handlers[] = {
|
||||
+ {
|
||||
+ .name = "mass_erase",
|
||||
+ .handler = nrf52_handle_mass_erase_command,
|
||||
+ .mode = COMMAND_EXEC,
|
||||
+ .help = "Erase all flash contents of the chip.",
|
||||
+ },
|
||||
+ COMMAND_REGISTRATION_DONE
|
||||
+};
|
||||
+
|
||||
+static const struct command_registration nrf52_command_handlers[] = {
|
||||
+ {
|
||||
+ .name = "nrf52",
|
||||
+ .mode = COMMAND_ANY,
|
||||
+ .help = "nrf52 flash command group",
|
||||
+ .usage = "",
|
||||
+ .chain = nrf52_exec_command_handlers,
|
||||
+ },
|
||||
+ COMMAND_REGISTRATION_DONE
|
||||
+};
|
||||
+
|
||||
+struct flash_driver nrf52_flash = {
|
||||
+ .name = "nrf52",
|
||||
+ .commands = nrf52_command_handlers,
|
||||
+ .flash_bank_command = nrf52_flash_bank_command,
|
||||
+ .info = nrf52_info,
|
||||
+ .erase = nrf52_erase,
|
||||
+ .protect = nrf52_protect,
|
||||
+ .write = nrf52_write,
|
||||
+ .read = default_flash_read,
|
||||
+ .probe = nrf52_probe,
|
||||
+ .auto_probe = nrf52_auto_probe,
|
||||
+ .erase_check = default_flash_blank_check,
|
||||
+ .protect_check = nrf52_protect_check,
|
||||
+};
|
||||
diff --git a/tcl/target/nrf52.cfg b/tcl/target/nrf52.cfg
|
||||
index c1cbf1a..a2567ff 100644
|
||||
--- a/tcl/target/nrf52.cfg
|
||||
+++ b/tcl/target/nrf52.cfg
|
||||
@@ -5,15 +5,22 @@
|
||||
source [find target/swj-dp.tcl]
|
||||
|
||||
if { [info exists CHIPNAME] } {
|
||||
- set _CHIPNAME $CHIPNAME
|
||||
+ set _CHIPNAME $CHIPNAME
|
||||
} else {
|
||||
- set _CHIPNAME nrf52
|
||||
+ set _CHIPNAME nrf52
|
||||
+}
|
||||
+
|
||||
+# Work-area is a space in RAM used for flash programming, by default use 16kB.
|
||||
+if { [info exists WORKAREASIZE] } {
|
||||
+ set _WORKAREASIZE $WORKAREASIZE
|
||||
+} else {
|
||||
+ set _WORKAREASIZE 0x4000
|
||||
}
|
||||
|
||||
if { [info exists CPUTAPID] } {
|
||||
- set _CPUTAPID $CPUTAPID
|
||||
+ set _CPUTAPID $CPUTAPID
|
||||
} else {
|
||||
- set _CPUTAPID 0x2ba01477
|
||||
+ set _CPUTAPID 0x2ba01477
|
||||
}
|
||||
|
||||
swj_newdap $_CHIPNAME cpu -expected-id $_CPUTAPID
|
||||
@@ -21,8 +28,15 @@ swj_newdap $_CHIPNAME cpu -expected-id $_CPUTAPID
|
||||
set _TARGETNAME $_CHIPNAME.cpu
|
||||
target create $_TARGETNAME cortex_m -chain-position $_TARGETNAME
|
||||
|
||||
-adapter_khz 10000
|
||||
+$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
|
||||
|
||||
-if { ![using_hla] } {
|
||||
- cortex_m reset_config sysresetreq
|
||||
+if {![using_hla]} {
|
||||
+ cortex_m reset_config sysresetreq
|
||||
}
|
||||
+
|
||||
+flash bank $_CHIPNAME.flash nrf52 0x00000000 0 1 1 $_TARGETNAME
|
||||
+flash bank $_CHIPNAME.uicr nrf52 0x10001000 0 1 1 $_TARGETNAME
|
||||
+
|
||||
+adapter_khz 1000
|
||||
+
|
||||
+$_TARGETNAME configure -event reset-end {}
|
|
@ -29,6 +29,7 @@
|
|||
;;; Copyright © 2016 Marius Bakke <mbakke@fastmail.com>
|
||||
;;; Copyright © 2016 Stefan Reichoer <stefan@xsteve.at>
|
||||
;;; Copyright © 2016 Dylan Jeffers <sapientech@sapientech@openmailbox.org>
|
||||
;;; Copyright © 2016 Alex Vong <alexvong1995@gmail.com>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
|
@ -3172,6 +3173,30 @@ (define-public python2-cython
|
|||
(inputs
|
||||
`(("python-2" ,python-2))))) ; this is not automatically changed
|
||||
|
||||
;; The RPython toolchain currently does not support Python 3.
|
||||
(define-public python2-rpython
|
||||
(package
|
||||
(name "python2-rpython")
|
||||
(version "0.1.4")
|
||||
(source
|
||||
(origin
|
||||
(method url-fetch)
|
||||
(uri (pypi-uri "rpython" version))
|
||||
(sha256
|
||||
(base32
|
||||
"07pps06fq4c4wmi5ii0sgh9zgwniz5y7frqhm28g3a154l163fxc"))))
|
||||
(build-system python-build-system)
|
||||
(arguments `(#:python ,python-2))
|
||||
(native-inputs
|
||||
`(("python2-pytest" ,python2-pytest) ; needed for running tests
|
||||
("python2-setuptools" ,python2-setuptools)))
|
||||
(home-page "https://rpython.readthedocs.org")
|
||||
(synopsis "Framework for implementing interpreters and virtual machines")
|
||||
(description "RPython is a translation and support framework for
|
||||
producing implementations of dynamic languages, emphasizing a clean separation
|
||||
between language specification and implementation aspects.")
|
||||
(license license:expat)))
|
||||
|
||||
;; This version of numpy is missing the documentation and is only used to
|
||||
;; build matplotlib which is required to build numpy's documentation.
|
||||
(define python-numpy-bootstrap
|
||||
|
@ -5258,30 +5283,28 @@ (define-public python2-backports-abc
|
|||
(define-public python-waf
|
||||
(package
|
||||
(name "python-waf")
|
||||
(version "1.9.1")
|
||||
(version "1.9.5")
|
||||
(source (origin
|
||||
(method url-fetch)
|
||||
(uri (string-append "https://waf.io/"
|
||||
(uri (string-append "http://waf.io/"
|
||||
"waf-" version ".tar.bz2"))
|
||||
(sha256
|
||||
(base32
|
||||
"1nc4qaqx2vsanlpp9mcwvf91xjqpkvcc6fcxd5sb4fwvaxamw5v6"))))
|
||||
"1sl3ipi2czds57rlzjnpdzqa0skx8asfvmh3qmibpvdwf15rpppg"))))
|
||||
(build-system python-build-system)
|
||||
(arguments
|
||||
'(#:phases
|
||||
(modify-phases %standard-phases
|
||||
(replace 'build
|
||||
(lambda _
|
||||
(zero? (begin
|
||||
(system* "python" "waf-light" "configure")
|
||||
(system* "python" "waf-light" "build")))))
|
||||
(lambda _
|
||||
(zero? (system* "python" "waf-light" "configure" "build"))))
|
||||
(replace 'check
|
||||
(lambda _
|
||||
(zero? (system* "python" "waf" "--version"))))
|
||||
(lambda _
|
||||
(zero? (system* "python" "waf" "--version"))))
|
||||
(replace 'install
|
||||
(lambda _
|
||||
(copy-file "waf" %output))))))
|
||||
(home-page "https://waf.io/")
|
||||
(lambda _
|
||||
(copy-file "waf" %output))))))
|
||||
(home-page "http://waf.io/")
|
||||
(synopsis "Python-based build system")
|
||||
(description
|
||||
"Waf is a Python-based framework for configuring, compiling and installing
|
||||
|
@ -9652,7 +9675,9 @@ (define-public python-pika
|
|||
"0nb4h08di432lv7dy2v9kpwgk0w92f24sqc2hw2s9vwr5b8v8xvj"))))
|
||||
(build-system python-build-system)
|
||||
(native-inputs
|
||||
`(("python-twisted" ,python-twisted)))
|
||||
`(("python-pyev" ,python-pyev)
|
||||
("python-tornado" ,python-tornado)
|
||||
("python-twisted" ,python-twisted)))
|
||||
(home-page "https://pika.readthedocs.org")
|
||||
(synopsis "Pure Python AMQP Client Library")
|
||||
(description
|
||||
|
@ -10214,6 +10239,8 @@ (define-public python-prompt-toolkit
|
|||
(base32
|
||||
"1vyjd0b7wciv55i19l44zy0adx8q7ss79lhy2r9d1rwz2y4822zg"))))
|
||||
(build-system python-build-system)
|
||||
(arguments
|
||||
'(#:tests? #f)) ; The test suite uses some Windows-specific data types.
|
||||
(inputs `(("python-wcwidth" ,python-wcwidth)
|
||||
("python-pygments" ,python-pygments)))
|
||||
(native-inputs `(("python-six" ,python-six)))
|
||||
|
@ -10681,6 +10708,8 @@ (define-public python-publicsuffix2
|
|||
(base32
|
||||
"06lx603gdwad5hc3hmn763ngq0rq9bzz1ni3ga72nzk5n872arkd"))))
|
||||
(build-system python-build-system)
|
||||
(arguments
|
||||
'(#:tests? #f)) ; The test suite requires network access.
|
||||
(home-page "https://github.com/pombredanne/python-publicsuffix2")
|
||||
(synopsis "Get a public suffix for a domain name using the Public Suffix List")
|
||||
(description "Get a public suffix for a domain name using the Public Suffix
|
||||
|
@ -11477,3 +11506,36 @@ (define-public python-flask-sqlalchemy
|
|||
(description
|
||||
"This package adds SQLAlchemy support to your Flask application.")
|
||||
(license license:bsd-3)))
|
||||
|
||||
(define-public python-pyev
|
||||
(package
|
||||
(name "python-pyev")
|
||||
(version "0.9.0")
|
||||
(source
|
||||
(origin
|
||||
(method url-fetch)
|
||||
(uri (pypi-uri "pyev" version))
|
||||
(sha256
|
||||
(base32
|
||||
"0rf603lc0s6zpa1nb25vhd8g4y337wg2wyz56i0agsdh7jchl0sx"))))
|
||||
(build-system python-build-system)
|
||||
(arguments
|
||||
`(#:tests? #f ; no test suite
|
||||
#:phases
|
||||
(modify-phases %standard-phases
|
||||
(add-after 'unpack 'patch
|
||||
(lambda* (#:key inputs #:allow-other-keys)
|
||||
(let ((libev (string-append (assoc-ref inputs "libev")
|
||||
"/lib/libev.so.4")))
|
||||
(substitute* "setup.py"
|
||||
(("libev_dll_name = find_library\\(\\\"ev\\\"\\)")
|
||||
(string-append "libev_dll_name = \"" libev "\"")))))))))
|
||||
(inputs
|
||||
`(("libev" ,libev)))
|
||||
(home-page "http://pythonhosted.org/pyev/")
|
||||
(synopsis "Python libev interface")
|
||||
(description "Pyev provides a Python interface to libev.")
|
||||
(license license:gpl3)))
|
||||
|
||||
(define-public python2-pyev
|
||||
(package-with-python2 python-pyev))
|
||||
|
|
|
@ -49,7 +49,7 @@ (define-public sdcc
|
|||
(arguments
|
||||
`(;; gputils is required for PIC ports
|
||||
#:configure-flags
|
||||
'("--disable-pic14-port" "--disable-pic16-port")
|
||||
'("--disable-pic14-port" "--disable-pic16-port" "--enable-ucsim")
|
||||
#:phases
|
||||
(modify-phases %standard-phases
|
||||
(add-after 'unpack 'patch-makefile
|
||||
|
|
|
@ -434,14 +434,14 @@ (define-public libva
|
|||
(define-public ffmpeg
|
||||
(package
|
||||
(name "ffmpeg")
|
||||
(version "3.1.5")
|
||||
(version "3.2")
|
||||
(source (origin
|
||||
(method url-fetch)
|
||||
(uri (string-append "https://ffmpeg.org/releases/ffmpeg-"
|
||||
version ".tar.xz"))
|
||||
(sha256
|
||||
(base32
|
||||
"16mqb1fs6ahqqv6a64dk4d8rp75ixdsipfzsz0vmc749yw2k3k29"))))
|
||||
"1nnmd3h9pr2zic08isjcm1cmvcyd0aimpayb9r4qy45bihdhrxw8"))))
|
||||
(build-system gnu-build-system)
|
||||
(inputs
|
||||
`(("fontconfig" ,fontconfig)
|
||||
|
@ -1287,16 +1287,16 @@ (define-public avidemux
|
|||
(define-public vapoursynth
|
||||
(package
|
||||
(name "vapoursynth")
|
||||
(version "34")
|
||||
(version "35")
|
||||
(source (origin
|
||||
(method url-fetch)
|
||||
(uri (string-append
|
||||
"https://github.com/vapoursynth/vapoursynth/archive/R"
|
||||
version ".tar.gz"))
|
||||
(file-name (string-append name "-" version))
|
||||
(file-name (string-append name "-" version ".tar.gz"))
|
||||
(sha256
|
||||
(base32
|
||||
"0rfldphg4gy3sdfffi5yzklqz93vsj2j6nny8snjbavnf161blyi"))))
|
||||
"0629ys2lf618n9cc644xlvx0vx52v2fp3sx14p4mx5rg9nlasb3n"))))
|
||||
(build-system gnu-build-system)
|
||||
(native-inputs
|
||||
`(("autoconf" ,autoconf)
|
||||
|
|
|
@ -48,14 +48,15 @@ (define-module (gnu packages vim)
|
|||
(define-public vim
|
||||
(package
|
||||
(name "vim")
|
||||
(version "8.0")
|
||||
(version "8.0.0054")
|
||||
(source (origin
|
||||
(method url-fetch)
|
||||
(uri (string-append "ftp://ftp.vim.org/pub/vim/unix/vim-"
|
||||
version ".tar.bz2"))
|
||||
(uri (string-append "https://github.com/vim/vim/archive/v"
|
||||
version ".tar.gz"))
|
||||
(file-name (string-append name "-" version ".tar.gz"))
|
||||
(sha256
|
||||
(base32
|
||||
"1s34rf8089klsbdx5l0iw7vjymir0kzfrx8wb30s31wygnq29axc"))))
|
||||
"018my9vmvflww9yzrrzgdbja8j075yxqj0czg351r6wrndqiv9vq"))))
|
||||
(build-system gnu-build-system)
|
||||
(arguments
|
||||
`(#:test-target "test"
|
||||
|
|
|
@ -139,7 +139,9 @@ (define (file-hash file)
|
|||
(write-file file port #:select? select?)
|
||||
(force-output port)
|
||||
(get-hash))
|
||||
(call-with-input-file file port-sha256))))
|
||||
(match file
|
||||
("-" (port-sha256 (current-input-port)))
|
||||
(_ (call-with-input-file file port-sha256))))))
|
||||
|
||||
(match args
|
||||
((file)
|
||||
|
|
|
@ -40,171 +40,6 @@
|
|||
namespace nix {
|
||||
|
||||
|
||||
MakeError(SQLiteError, Error);
|
||||
MakeError(SQLiteBusy, SQLiteError);
|
||||
|
||||
|
||||
static void throwSQLiteError(sqlite3 * db, const format & f)
|
||||
__attribute__ ((noreturn));
|
||||
|
||||
static void throwSQLiteError(sqlite3 * db, const format & f)
|
||||
{
|
||||
int err = sqlite3_errcode(db);
|
||||
if (err == SQLITE_BUSY || err == SQLITE_PROTOCOL) {
|
||||
if (err == SQLITE_PROTOCOL)
|
||||
printMsg(lvlError, "warning: SQLite database is busy (SQLITE_PROTOCOL)");
|
||||
else {
|
||||
static bool warned = false;
|
||||
if (!warned) {
|
||||
printMsg(lvlError, "warning: SQLite database is busy");
|
||||
warned = true;
|
||||
}
|
||||
}
|
||||
/* Sleep for a while since retrying the transaction right away
|
||||
is likely to fail again. */
|
||||
#if HAVE_NANOSLEEP
|
||||
struct timespec t;
|
||||
t.tv_sec = 0;
|
||||
t.tv_nsec = (random() % 100) * 1000 * 1000; /* <= 0.1s */
|
||||
nanosleep(&t, 0);
|
||||
#else
|
||||
sleep(1);
|
||||
#endif
|
||||
throw SQLiteBusy(format("%1%: %2%") % f.str() % sqlite3_errmsg(db));
|
||||
}
|
||||
else
|
||||
throw SQLiteError(format("%1%: %2%") % f.str() % sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
|
||||
/* Convenience macros for retrying a SQLite transaction. */
|
||||
#define retry_sqlite while (1) { try {
|
||||
#define end_retry_sqlite break; } catch (SQLiteBusy & e) { } }
|
||||
|
||||
|
||||
SQLite::~SQLite()
|
||||
{
|
||||
try {
|
||||
if (db && sqlite3_close(db) != SQLITE_OK)
|
||||
throwSQLiteError(db, "closing database");
|
||||
} catch (...) {
|
||||
ignoreException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SQLiteStmt::create(sqlite3 * db, const string & s)
|
||||
{
|
||||
checkInterrupt();
|
||||
assert(!stmt);
|
||||
if (sqlite3_prepare_v2(db, s.c_str(), -1, &stmt, 0) != SQLITE_OK)
|
||||
throwSQLiteError(db, "creating statement");
|
||||
this->db = db;
|
||||
}
|
||||
|
||||
|
||||
void SQLiteStmt::reset()
|
||||
{
|
||||
assert(stmt);
|
||||
/* Note: sqlite3_reset() returns the error code for the most
|
||||
recent call to sqlite3_step(). So ignore it. */
|
||||
sqlite3_reset(stmt);
|
||||
curArg = 1;
|
||||
}
|
||||
|
||||
|
||||
SQLiteStmt::~SQLiteStmt()
|
||||
{
|
||||
try {
|
||||
if (stmt && sqlite3_finalize(stmt) != SQLITE_OK)
|
||||
throwSQLiteError(db, "finalizing statement");
|
||||
} catch (...) {
|
||||
ignoreException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SQLiteStmt::bind(const string & value)
|
||||
{
|
||||
if (sqlite3_bind_text(stmt, curArg++, value.c_str(), -1, SQLITE_TRANSIENT) != SQLITE_OK)
|
||||
throwSQLiteError(db, "binding argument");
|
||||
}
|
||||
|
||||
|
||||
void SQLiteStmt::bind(int value)
|
||||
{
|
||||
if (sqlite3_bind_int(stmt, curArg++, value) != SQLITE_OK)
|
||||
throwSQLiteError(db, "binding argument");
|
||||
}
|
||||
|
||||
|
||||
void SQLiteStmt::bind64(long long value)
|
||||
{
|
||||
if (sqlite3_bind_int64(stmt, curArg++, value) != SQLITE_OK)
|
||||
throwSQLiteError(db, "binding argument");
|
||||
}
|
||||
|
||||
|
||||
void SQLiteStmt::bind()
|
||||
{
|
||||
if (sqlite3_bind_null(stmt, curArg++) != SQLITE_OK)
|
||||
throwSQLiteError(db, "binding argument");
|
||||
}
|
||||
|
||||
|
||||
/* Helper class to ensure that prepared statements are reset when
|
||||
leaving the scope that uses them. Unfinished prepared statements
|
||||
prevent transactions from being aborted, and can cause locks to be
|
||||
kept when they should be released. */
|
||||
struct SQLiteStmtUse
|
||||
{
|
||||
SQLiteStmt & stmt;
|
||||
SQLiteStmtUse(SQLiteStmt & stmt) : stmt(stmt)
|
||||
{
|
||||
stmt.reset();
|
||||
}
|
||||
~SQLiteStmtUse()
|
||||
{
|
||||
try {
|
||||
stmt.reset();
|
||||
} catch (...) {
|
||||
ignoreException();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct SQLiteTxn
|
||||
{
|
||||
bool active;
|
||||
sqlite3 * db;
|
||||
|
||||
SQLiteTxn(sqlite3 * db) : active(false) {
|
||||
this->db = db;
|
||||
if (sqlite3_exec(db, "begin;", 0, 0, 0) != SQLITE_OK)
|
||||
throwSQLiteError(db, "starting transaction");
|
||||
active = true;
|
||||
}
|
||||
|
||||
void commit()
|
||||
{
|
||||
if (sqlite3_exec(db, "commit;", 0, 0, 0) != SQLITE_OK)
|
||||
throwSQLiteError(db, "committing transaction");
|
||||
active = false;
|
||||
}
|
||||
|
||||
~SQLiteTxn()
|
||||
{
|
||||
try {
|
||||
if (active && sqlite3_exec(db, "rollback;", 0, 0, 0) != SQLITE_OK)
|
||||
throwSQLiteError(db, "aborting transaction");
|
||||
} catch (...) {
|
||||
ignoreException();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void checkStoreNotSymlink()
|
||||
{
|
||||
if (getEnv("NIX_IGNORE_SYMLINK_STORE") == "1") return;
|
||||
|
@ -494,6 +329,7 @@ void LocalStore::openDB(bool create)
|
|||
// ensure efficient lookup.
|
||||
stmtQueryPathFromHashPart.create(db,
|
||||
"select path from ValidPaths where path >= ? limit 1;");
|
||||
stmtQueryValidPaths.create(db, "select path from ValidPaths");
|
||||
}
|
||||
|
||||
|
||||
|
@ -688,23 +524,16 @@ void LocalStore::checkDerivationOutputs(const Path & drvPath, const Derivation &
|
|||
}
|
||||
|
||||
|
||||
unsigned long long LocalStore::addValidPath(const ValidPathInfo & info, bool checkOutputs)
|
||||
uint64_t LocalStore::addValidPath(const ValidPathInfo & info, bool checkOutputs)
|
||||
{
|
||||
SQLiteStmtUse use(stmtRegisterValidPath);
|
||||
stmtRegisterValidPath.bind(info.path);
|
||||
stmtRegisterValidPath.bind("sha256:" + printHash(info.hash));
|
||||
stmtRegisterValidPath.bind(info.registrationTime == 0 ? time(0) : info.registrationTime);
|
||||
if (info.deriver != "")
|
||||
stmtRegisterValidPath.bind(info.deriver);
|
||||
else
|
||||
stmtRegisterValidPath.bind(); // null
|
||||
if (info.narSize != 0)
|
||||
stmtRegisterValidPath.bind64(info.narSize);
|
||||
else
|
||||
stmtRegisterValidPath.bind(); // null
|
||||
if (sqlite3_step(stmtRegisterValidPath) != SQLITE_DONE)
|
||||
throwSQLiteError(db, format("registering valid path `%1%' in database") % info.path);
|
||||
unsigned long long id = sqlite3_last_insert_rowid(db);
|
||||
stmtRegisterValidPath.use()
|
||||
(info.path)
|
||||
("sha256:" + printHash(info.hash))
|
||||
(info.registrationTime == 0 ? time(0) : info.registrationTime)
|
||||
(info.deriver, info.deriver != "")
|
||||
(info.narSize, info.narSize != 0)
|
||||
.exec();
|
||||
uint64_t id = sqlite3_last_insert_rowid(db);
|
||||
|
||||
/* If this is a derivation, then store the derivation outputs in
|
||||
the database. This is useful for the garbage collector: it can
|
||||
|
@ -720,13 +549,12 @@ unsigned long long LocalStore::addValidPath(const ValidPathInfo & info, bool che
|
|||
registration above is undone. */
|
||||
if (checkOutputs) checkDerivationOutputs(info.path, drv);
|
||||
|
||||
foreach (DerivationOutputs::iterator, i, drv.outputs) {
|
||||
SQLiteStmtUse use(stmtAddDerivationOutput);
|
||||
stmtAddDerivationOutput.bind(id);
|
||||
stmtAddDerivationOutput.bind(i->first);
|
||||
stmtAddDerivationOutput.bind(i->second.path);
|
||||
if (sqlite3_step(stmtAddDerivationOutput) != SQLITE_DONE)
|
||||
throwSQLiteError(db, format("adding derivation output for `%1%' in database") % info.path);
|
||||
for (auto & i : drv.outputs) {
|
||||
stmtAddDerivationOutput.use()
|
||||
(id)
|
||||
(i.first)
|
||||
(i.second.path)
|
||||
.exec();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -734,76 +562,52 @@ unsigned long long LocalStore::addValidPath(const ValidPathInfo & info, bool che
|
|||
}
|
||||
|
||||
|
||||
void LocalStore::addReference(unsigned long long referrer, unsigned long long reference)
|
||||
void LocalStore::addReference(uint64_t referrer, uint64_t reference)
|
||||
{
|
||||
SQLiteStmtUse use(stmtAddReference);
|
||||
stmtAddReference.bind(referrer);
|
||||
stmtAddReference.bind(reference);
|
||||
if (sqlite3_step(stmtAddReference) != SQLITE_DONE)
|
||||
throwSQLiteError(db, "adding reference to database");
|
||||
stmtAddReference.use()(referrer)(reference).exec();
|
||||
}
|
||||
|
||||
|
||||
void LocalStore::registerFailedPath(const Path & path)
|
||||
{
|
||||
retry_sqlite {
|
||||
SQLiteStmtUse use(stmtRegisterFailedPath);
|
||||
stmtRegisterFailedPath.bind(path);
|
||||
stmtRegisterFailedPath.bind(time(0));
|
||||
if (sqlite3_step(stmtRegisterFailedPath) != SQLITE_DONE)
|
||||
throwSQLiteError(db, format("registering failed path `%1%'") % path);
|
||||
} end_retry_sqlite;
|
||||
retrySQLite<void>([&]() {
|
||||
stmtRegisterFailedPath.use()(path)(time(0)).step();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
bool LocalStore::hasPathFailed(const Path & path)
|
||||
{
|
||||
retry_sqlite {
|
||||
SQLiteStmtUse use(stmtHasPathFailed);
|
||||
stmtHasPathFailed.bind(path);
|
||||
int res = sqlite3_step(stmtHasPathFailed);
|
||||
if (res != SQLITE_DONE && res != SQLITE_ROW)
|
||||
throwSQLiteError(db, "querying whether path failed");
|
||||
return res == SQLITE_ROW;
|
||||
} end_retry_sqlite;
|
||||
return retrySQLite<bool>([&]() {
|
||||
return stmtHasPathFailed.use()(path).next();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
PathSet LocalStore::queryFailedPaths()
|
||||
{
|
||||
retry_sqlite {
|
||||
SQLiteStmtUse use(stmtQueryFailedPaths);
|
||||
return retrySQLite<PathSet>([&]() {
|
||||
auto useQueryFailedPaths(stmtQueryFailedPaths.use());
|
||||
|
||||
PathSet res;
|
||||
int r;
|
||||
while ((r = sqlite3_step(stmtQueryFailedPaths)) == SQLITE_ROW) {
|
||||
const char * s = (const char *) sqlite3_column_text(stmtQueryFailedPaths, 0);
|
||||
assert(s);
|
||||
res.insert(s);
|
||||
}
|
||||
|
||||
if (r != SQLITE_DONE)
|
||||
throwSQLiteError(db, "error querying failed paths");
|
||||
while (useQueryFailedPaths.next())
|
||||
res.insert(useQueryFailedPaths.getStr(0));
|
||||
|
||||
return res;
|
||||
} end_retry_sqlite;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void LocalStore::clearFailedPaths(const PathSet & paths)
|
||||
{
|
||||
retry_sqlite {
|
||||
retrySQLite<void>([&]() {
|
||||
SQLiteTxn txn(db);
|
||||
|
||||
foreach (PathSet::const_iterator, i, paths) {
|
||||
SQLiteStmtUse use(stmtClearFailedPath);
|
||||
stmtClearFailedPath.bind(*i);
|
||||
if (sqlite3_step(stmtClearFailedPath) != SQLITE_DONE)
|
||||
throwSQLiteError(db, format("clearing failed path `%1%' in database") % *i);
|
||||
}
|
||||
for (auto & path : paths)
|
||||
stmtClearFailedPath.use()(path).exec();
|
||||
|
||||
txn.commit();
|
||||
} end_retry_sqlite;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -828,47 +632,34 @@ ValidPathInfo LocalStore::queryPathInfo(const Path & path)
|
|||
|
||||
assertStorePath(path);
|
||||
|
||||
retry_sqlite {
|
||||
return retrySQLite<ValidPathInfo>([&]() {
|
||||
|
||||
/* Get the path info. */
|
||||
SQLiteStmtUse use1(stmtQueryPathInfo);
|
||||
auto useQueryPathInfo(stmtQueryPathInfo.use()(path));
|
||||
|
||||
stmtQueryPathInfo.bind(path);
|
||||
if (!useQueryPathInfo.next())
|
||||
throw Error(format("path `%1%' is not valid") % path);
|
||||
|
||||
int r = sqlite3_step(stmtQueryPathInfo);
|
||||
if (r == SQLITE_DONE) throw Error(format("path `%1%' is not valid") % path);
|
||||
if (r != SQLITE_ROW) throwSQLiteError(db, "querying path in database");
|
||||
info.id = useQueryPathInfo.getInt(0);
|
||||
|
||||
info.id = sqlite3_column_int(stmtQueryPathInfo, 0);
|
||||
info.hash = parseHashField(path, useQueryPathInfo.getStr(1));
|
||||
|
||||
const char * s = (const char *) sqlite3_column_text(stmtQueryPathInfo, 1);
|
||||
assert(s);
|
||||
info.hash = parseHashField(path, s);
|
||||
info.registrationTime = useQueryPathInfo.getInt(2);
|
||||
|
||||
info.registrationTime = sqlite3_column_int(stmtQueryPathInfo, 2);
|
||||
|
||||
s = (const char *) sqlite3_column_text(stmtQueryPathInfo, 3);
|
||||
auto s = (const char *) sqlite3_column_text(stmtQueryPathInfo, 3);
|
||||
if (s) info.deriver = s;
|
||||
|
||||
/* Note that narSize = NULL yields 0. */
|
||||
info.narSize = sqlite3_column_int64(stmtQueryPathInfo, 4);
|
||||
info.narSize = useQueryPathInfo.getInt(4);
|
||||
|
||||
/* Get the references. */
|
||||
SQLiteStmtUse use2(stmtQueryReferences);
|
||||
auto useQueryReferences(stmtQueryReferences.use()(info.id));
|
||||
|
||||
stmtQueryReferences.bind(info.id);
|
||||
|
||||
while ((r = sqlite3_step(stmtQueryReferences)) == SQLITE_ROW) {
|
||||
s = (const char *) sqlite3_column_text(stmtQueryReferences, 0);
|
||||
assert(s);
|
||||
info.references.insert(s);
|
||||
}
|
||||
|
||||
if (r != SQLITE_DONE)
|
||||
throwSQLiteError(db, format("error getting references of `%1%'") % path);
|
||||
while (useQueryReferences.next())
|
||||
info.references.insert(useQueryReferences.getStr(0));
|
||||
|
||||
return info;
|
||||
} end_retry_sqlite;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -876,78 +667,56 @@ ValidPathInfo LocalStore::queryPathInfo(const Path & path)
|
|||
narSize field. */
|
||||
void LocalStore::updatePathInfo(const ValidPathInfo & info)
|
||||
{
|
||||
SQLiteStmtUse use(stmtUpdatePathInfo);
|
||||
if (info.narSize != 0)
|
||||
stmtUpdatePathInfo.bind64(info.narSize);
|
||||
else
|
||||
stmtUpdatePathInfo.bind(); // null
|
||||
stmtUpdatePathInfo.bind("sha256:" + printHash(info.hash));
|
||||
stmtUpdatePathInfo.bind(info.path);
|
||||
if (sqlite3_step(stmtUpdatePathInfo) != SQLITE_DONE)
|
||||
throwSQLiteError(db, format("updating info of path `%1%' in database") % info.path);
|
||||
stmtUpdatePathInfo.use()
|
||||
(info.narSize, info.narSize != 0)
|
||||
("sha256:" + printHash(info.hash))
|
||||
(info.path)
|
||||
.exec();
|
||||
}
|
||||
|
||||
|
||||
unsigned long long LocalStore::queryValidPathId(const Path & path)
|
||||
uint64_t LocalStore::queryValidPathId(const Path & path)
|
||||
{
|
||||
SQLiteStmtUse use(stmtQueryPathInfo);
|
||||
stmtQueryPathInfo.bind(path);
|
||||
int res = sqlite3_step(stmtQueryPathInfo);
|
||||
if (res == SQLITE_ROW) return sqlite3_column_int(stmtQueryPathInfo, 0);
|
||||
if (res == SQLITE_DONE) throw Error(format("path `%1%' is not valid") % path);
|
||||
throwSQLiteError(db, "querying path in database");
|
||||
auto use(stmtQueryPathInfo.use()(path));
|
||||
if (!use.next())
|
||||
throw Error(format("path ‘%1%’ is not valid") % path);
|
||||
return use.getInt(0);
|
||||
}
|
||||
|
||||
|
||||
bool LocalStore::isValidPath_(const Path & path)
|
||||
{
|
||||
SQLiteStmtUse use(stmtQueryPathInfo);
|
||||
stmtQueryPathInfo.bind(path);
|
||||
int res = sqlite3_step(stmtQueryPathInfo);
|
||||
if (res != SQLITE_DONE && res != SQLITE_ROW)
|
||||
throwSQLiteError(db, "querying path in database");
|
||||
return res == SQLITE_ROW;
|
||||
return stmtQueryPathInfo.use()(path).next();
|
||||
}
|
||||
|
||||
|
||||
bool LocalStore::isValidPath(const Path & path)
|
||||
{
|
||||
retry_sqlite {
|
||||
return retrySQLite<bool>([&]() {
|
||||
return isValidPath_(path);
|
||||
} end_retry_sqlite;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
PathSet LocalStore::queryValidPaths(const PathSet & paths)
|
||||
{
|
||||
retry_sqlite {
|
||||
return retrySQLite<PathSet>([&]() {
|
||||
PathSet res;
|
||||
foreach (PathSet::const_iterator, i, paths)
|
||||
if (isValidPath_(*i)) res.insert(*i);
|
||||
return res;
|
||||
} end_retry_sqlite;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
PathSet LocalStore::queryAllValidPaths()
|
||||
{
|
||||
retry_sqlite {
|
||||
SQLiteStmt stmt;
|
||||
stmt.create(db, "select path from ValidPaths");
|
||||
|
||||
return retrySQLite<PathSet>([&]() {
|
||||
auto use(stmtQueryValidPaths.use());
|
||||
PathSet res;
|
||||
int r;
|
||||
while ((r = sqlite3_step(stmt)) == SQLITE_ROW) {
|
||||
const char * s = (const char *) sqlite3_column_text(stmt, 0);
|
||||
assert(s);
|
||||
res.insert(s);
|
||||
}
|
||||
|
||||
if (r != SQLITE_DONE)
|
||||
throwSQLiteError(db, "error getting valid paths");
|
||||
|
||||
while (use.next()) res.insert(use.getStr(0));
|
||||
return res;
|
||||
} end_retry_sqlite;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -961,28 +730,19 @@ void LocalStore::queryReferences(const Path & path,
|
|||
|
||||
void LocalStore::queryReferrers_(const Path & path, PathSet & referrers)
|
||||
{
|
||||
SQLiteStmtUse use(stmtQueryReferrers);
|
||||
auto useQueryReferrers(stmtQueryReferrers.use()(path));
|
||||
|
||||
stmtQueryReferrers.bind(path);
|
||||
|
||||
int r;
|
||||
while ((r = sqlite3_step(stmtQueryReferrers)) == SQLITE_ROW) {
|
||||
const char * s = (const char *) sqlite3_column_text(stmtQueryReferrers, 0);
|
||||
assert(s);
|
||||
referrers.insert(s);
|
||||
}
|
||||
|
||||
if (r != SQLITE_DONE)
|
||||
throwSQLiteError(db, format("error getting references of `%1%'") % path);
|
||||
while (useQueryReferrers.next())
|
||||
referrers.insert(useQueryReferrers.getStr(0));
|
||||
}
|
||||
|
||||
|
||||
void LocalStore::queryReferrers(const Path & path, PathSet & referrers)
|
||||
{
|
||||
assertStorePath(path);
|
||||
retry_sqlite {
|
||||
return retrySQLite<void>([&]() {
|
||||
queryReferrers_(path, referrers);
|
||||
} end_retry_sqlite;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -996,67 +756,43 @@ PathSet LocalStore::queryValidDerivers(const Path & path)
|
|||
{
|
||||
assertStorePath(path);
|
||||
|
||||
retry_sqlite {
|
||||
SQLiteStmtUse use(stmtQueryValidDerivers);
|
||||
stmtQueryValidDerivers.bind(path);
|
||||
return retrySQLite<PathSet>([&]() {
|
||||
auto useQueryValidDerivers(stmtQueryValidDerivers.use()(path));
|
||||
|
||||
PathSet derivers;
|
||||
int r;
|
||||
while ((r = sqlite3_step(stmtQueryValidDerivers)) == SQLITE_ROW) {
|
||||
const char * s = (const char *) sqlite3_column_text(stmtQueryValidDerivers, 1);
|
||||
assert(s);
|
||||
derivers.insert(s);
|
||||
}
|
||||
|
||||
if (r != SQLITE_DONE)
|
||||
throwSQLiteError(db, format("error getting valid derivers of `%1%'") % path);
|
||||
while (useQueryValidDerivers.next())
|
||||
derivers.insert(useQueryValidDerivers.getStr(1));
|
||||
|
||||
return derivers;
|
||||
} end_retry_sqlite;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
PathSet LocalStore::queryDerivationOutputs(const Path & path)
|
||||
{
|
||||
retry_sqlite {
|
||||
SQLiteStmtUse use(stmtQueryDerivationOutputs);
|
||||
stmtQueryDerivationOutputs.bind(queryValidPathId(path));
|
||||
return retrySQLite<PathSet>([&]() {
|
||||
auto useQueryDerivationOutputs(stmtQueryDerivationOutputs.use()(queryValidPathId(path)));
|
||||
|
||||
PathSet outputs;
|
||||
int r;
|
||||
while ((r = sqlite3_step(stmtQueryDerivationOutputs)) == SQLITE_ROW) {
|
||||
const char * s = (const char *) sqlite3_column_text(stmtQueryDerivationOutputs, 1);
|
||||
assert(s);
|
||||
outputs.insert(s);
|
||||
}
|
||||
|
||||
if (r != SQLITE_DONE)
|
||||
throwSQLiteError(db, format("error getting outputs of `%1%'") % path);
|
||||
while (useQueryDerivationOutputs.next())
|
||||
outputs.insert(useQueryDerivationOutputs.getStr(1));
|
||||
|
||||
return outputs;
|
||||
} end_retry_sqlite;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
StringSet LocalStore::queryDerivationOutputNames(const Path & path)
|
||||
{
|
||||
retry_sqlite {
|
||||
SQLiteStmtUse use(stmtQueryDerivationOutputs);
|
||||
stmtQueryDerivationOutputs.bind(queryValidPathId(path));
|
||||
return retrySQLite<StringSet>([&]() {
|
||||
auto useQueryDerivationOutputs(stmtQueryDerivationOutputs.use()(queryValidPathId(path)));
|
||||
|
||||
StringSet outputNames;
|
||||
int r;
|
||||
while ((r = sqlite3_step(stmtQueryDerivationOutputs)) == SQLITE_ROW) {
|
||||
const char * s = (const char *) sqlite3_column_text(stmtQueryDerivationOutputs, 0);
|
||||
assert(s);
|
||||
outputNames.insert(s);
|
||||
}
|
||||
|
||||
if (r != SQLITE_DONE)
|
||||
throwSQLiteError(db, format("error getting output names of `%1%'") % path);
|
||||
while (useQueryDerivationOutputs.next())
|
||||
outputNames.insert(useQueryDerivationOutputs.getStr(0));
|
||||
|
||||
return outputNames;
|
||||
} end_retry_sqlite;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -1066,17 +802,14 @@ Path LocalStore::queryPathFromHashPart(const string & hashPart)
|
|||
|
||||
Path prefix = settings.nixStore + "/" + hashPart;
|
||||
|
||||
retry_sqlite {
|
||||
SQLiteStmtUse use(stmtQueryPathFromHashPart);
|
||||
stmtQueryPathFromHashPart.bind(prefix);
|
||||
return retrySQLite<Path>([&]() -> Path {
|
||||
auto useQueryPathFromHashPart(stmtQueryPathFromHashPart.use()(prefix));
|
||||
|
||||
int res = sqlite3_step(stmtQueryPathFromHashPart);
|
||||
if (res == SQLITE_DONE) return "";
|
||||
if (res != SQLITE_ROW) throwSQLiteError(db, "finding path in database");
|
||||
if (!useQueryPathFromHashPart.next()) return "";
|
||||
|
||||
const char * s = (const char *) sqlite3_column_text(stmtQueryPathFromHashPart, 0);
|
||||
return s && prefix.compare(0, prefix.size(), s, prefix.size()) == 0 ? s : "";
|
||||
} end_retry_sqlite;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -1306,7 +1039,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
|
|||
* expense of some speed of the path registering operation. */
|
||||
if (settings.syncBeforeRegistering) sync();
|
||||
|
||||
retry_sqlite {
|
||||
return retrySQLite<void>([&]() {
|
||||
SQLiteTxn txn(db);
|
||||
PathSet paths;
|
||||
|
||||
|
@ -1319,10 +1052,10 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
|
|||
paths.insert(i->path);
|
||||
}
|
||||
|
||||
foreach (ValidPathInfos::const_iterator, i, infos) {
|
||||
unsigned long long referrer = queryValidPathId(i->path);
|
||||
foreach (PathSet::iterator, j, i->references)
|
||||
addReference(referrer, queryValidPathId(*j));
|
||||
for (auto & i : infos) {
|
||||
auto referrer = queryValidPathId(i.path);
|
||||
for (auto & j : i.references)
|
||||
addReference(referrer, queryValidPathId(j));
|
||||
}
|
||||
|
||||
/* Check that the derivation outputs are correct. We can't do
|
||||
|
@ -1343,7 +1076,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
|
|||
topoSortPaths(*this, paths);
|
||||
|
||||
txn.commit();
|
||||
} end_retry_sqlite;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -1355,12 +1088,7 @@ void LocalStore::invalidatePath(const Path & path)
|
|||
|
||||
drvHashes.erase(path);
|
||||
|
||||
SQLiteStmtUse use(stmtInvalidatePath);
|
||||
|
||||
stmtInvalidatePath.bind(path);
|
||||
|
||||
if (sqlite3_step(stmtInvalidatePath) != SQLITE_DONE)
|
||||
throwSQLiteError(db, format("invalidating path `%1%' in database") % path);
|
||||
stmtInvalidatePath.use()(path).exec();
|
||||
|
||||
/* Note that the foreign key constraints on the Refs table take
|
||||
care of deleting the references entries for `path'. */
|
||||
|
@ -1733,7 +1461,7 @@ void LocalStore::invalidatePathChecked(const Path & path)
|
|||
{
|
||||
assertStorePath(path);
|
||||
|
||||
retry_sqlite {
|
||||
retrySQLite<void>([&]() {
|
||||
SQLiteTxn txn(db);
|
||||
|
||||
if (isValidPath_(path)) {
|
||||
|
@ -1746,7 +1474,7 @@ void LocalStore::invalidatePathChecked(const Path & path)
|
|||
}
|
||||
|
||||
txn.commit();
|
||||
} end_retry_sqlite;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include "sqlite.hh"
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "pathlocks.hh"
|
||||
#include "store-api.hh"
|
||||
#include "util.hh"
|
||||
#include "pathlocks.hh"
|
||||
|
||||
|
||||
class sqlite3;
|
||||
class sqlite3_stmt;
|
||||
|
||||
|
||||
namespace nix {
|
||||
|
@ -52,34 +49,6 @@ struct RunningSubstituter
|
|||
};
|
||||
|
||||
|
||||
/* Wrapper object to close the SQLite database automatically. */
|
||||
struct SQLite
|
||||
{
|
||||
sqlite3 * db;
|
||||
SQLite() { db = 0; }
|
||||
~SQLite();
|
||||
operator sqlite3 * () { return db; }
|
||||
};
|
||||
|
||||
|
||||
/* Wrapper object to create and destroy SQLite prepared statements. */
|
||||
struct SQLiteStmt
|
||||
{
|
||||
sqlite3 * db;
|
||||
sqlite3_stmt * stmt;
|
||||
unsigned int curArg;
|
||||
SQLiteStmt() { stmt = 0; }
|
||||
void create(sqlite3 * db, const string & s);
|
||||
void reset();
|
||||
~SQLiteStmt();
|
||||
operator sqlite3_stmt * () { return stmt; }
|
||||
void bind(const string & value);
|
||||
void bind(int value);
|
||||
void bind64(long long value);
|
||||
void bind();
|
||||
};
|
||||
|
||||
|
||||
class LocalStore : public StoreAPI
|
||||
{
|
||||
private:
|
||||
|
@ -238,6 +207,7 @@ private:
|
|||
SQLiteStmt stmtQueryValidDerivers;
|
||||
SQLiteStmt stmtQueryDerivationOutputs;
|
||||
SQLiteStmt stmtQueryPathFromHashPart;
|
||||
SQLiteStmt stmtQueryValidPaths;
|
||||
|
||||
/* Cache for pathContentsGood(). */
|
||||
std::map<Path, bool> pathContentsGoodCache;
|
||||
|
@ -254,11 +224,11 @@ private:
|
|||
|
||||
void makeStoreWritable();
|
||||
|
||||
unsigned long long queryValidPathId(const Path & path);
|
||||
uint64_t queryValidPathId(const Path & path);
|
||||
|
||||
unsigned long long addValidPath(const ValidPathInfo & info, bool checkOutputs = true);
|
||||
uint64_t addValidPath(const ValidPathInfo & info, bool checkOutputs = true);
|
||||
|
||||
void addReference(unsigned long long referrer, unsigned long long reference);
|
||||
void addReference(uint64_t referrer, uint64_t reference);
|
||||
|
||||
void appendReferrer(const Path & from, const Path & to, bool lock);
|
||||
|
||||
|
|
|
@ -148,10 +148,23 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
|
|||
inodeHash.insert(st.st_ino);
|
||||
return;
|
||||
}
|
||||
if (errno != EEXIST)
|
||||
|
||||
switch (errno) {
|
||||
case EEXIST:
|
||||
/* Fall through if another process created ‘linkPath’ before
|
||||
we did. */
|
||||
break;
|
||||
|
||||
case ENOSPC:
|
||||
/* On ext4, that probably means the directory index is full. When
|
||||
that happens, it's fine to ignore it: we just effectively
|
||||
disable deduplication of this file. */
|
||||
printMsg(lvlInfo, format("cannot link `%1%' to `%2%': %m") % linkPath % path);
|
||||
return;
|
||||
|
||||
default:
|
||||
throw SysError(format("cannot link `%1%' to `%2%'") % linkPath % path);
|
||||
/* Fall through if another process created ‘linkPath’ before
|
||||
we did. */
|
||||
}
|
||||
}
|
||||
|
||||
/* Yes! We've seen a file with the same contents. Replace the
|
||||
|
@ -195,8 +208,8 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
|
|||
printMsg(lvlInfo, format("`%1%' has maximum number of links") % linkPath);
|
||||
return;
|
||||
}
|
||||
throw SysError(format("cannot link `%1%' to `%2%'") % tempLink % linkPath);
|
||||
}
|
||||
throw SysError(format("cannot link `%1%' to `%2%'") % tempLink % linkPath);
|
||||
}
|
||||
|
||||
/* Atomically replace the old file with the new hard link. */
|
||||
if (rename(tempLink.c_str(), path.c_str()) == -1) {
|
||||
|
|
166
nix/libstore/sqlite.cc
Normal file
166
nix/libstore/sqlite.cc
Normal file
|
@ -0,0 +1,166 @@
|
|||
#include "sqlite.hh"
|
||||
#include "util.hh"
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
namespace nix {
|
||||
|
||||
[[noreturn]] void throwSQLiteError(sqlite3 * db, const format & f)
|
||||
{
|
||||
int err = sqlite3_errcode(db);
|
||||
if (err == SQLITE_BUSY || err == SQLITE_PROTOCOL) {
|
||||
if (err == SQLITE_PROTOCOL)
|
||||
printMsg(lvlError, "warning: SQLite database is busy (SQLITE_PROTOCOL)");
|
||||
else {
|
||||
static bool warned = false;
|
||||
if (!warned) {
|
||||
printMsg(lvlError, "warning: SQLite database is busy");
|
||||
warned = true;
|
||||
}
|
||||
}
|
||||
/* Sleep for a while since retrying the transaction right away
|
||||
is likely to fail again. */
|
||||
#if HAVE_NANOSLEEP
|
||||
struct timespec t;
|
||||
t.tv_sec = 0;
|
||||
t.tv_nsec = (random() % 100) * 1000 * 1000; /* <= 0.1s */
|
||||
nanosleep(&t, 0);
|
||||
#else
|
||||
sleep(1);
|
||||
#endif
|
||||
throw SQLiteBusy(format("%1%: %2%") % f.str() % sqlite3_errmsg(db));
|
||||
}
|
||||
else
|
||||
throw SQLiteError(format("%1%: %2%") % f.str() % sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
SQLite::~SQLite()
|
||||
{
|
||||
try {
|
||||
if (db && sqlite3_close(db) != SQLITE_OK)
|
||||
throwSQLiteError(db, "closing database");
|
||||
} catch (...) {
|
||||
ignoreException();
|
||||
}
|
||||
}
|
||||
|
||||
void SQLiteStmt::create(sqlite3 * db, const string & s)
|
||||
{
|
||||
checkInterrupt();
|
||||
assert(!stmt);
|
||||
if (sqlite3_prepare_v2(db, s.c_str(), -1, &stmt, 0) != SQLITE_OK)
|
||||
throwSQLiteError(db, "creating statement");
|
||||
this->db = db;
|
||||
}
|
||||
|
||||
SQLiteStmt::~SQLiteStmt()
|
||||
{
|
||||
try {
|
||||
if (stmt && sqlite3_finalize(stmt) != SQLITE_OK)
|
||||
throwSQLiteError(db, "finalizing statement");
|
||||
} catch (...) {
|
||||
ignoreException();
|
||||
}
|
||||
}
|
||||
|
||||
SQLiteStmt::Use::Use(SQLiteStmt & stmt)
|
||||
: stmt(stmt)
|
||||
{
|
||||
assert(stmt.stmt);
|
||||
/* Note: sqlite3_reset() returns the error code for the most
|
||||
recent call to sqlite3_step(). So ignore it. */
|
||||
sqlite3_reset(stmt);
|
||||
}
|
||||
|
||||
SQLiteStmt::Use::~Use()
|
||||
{
|
||||
sqlite3_reset(stmt);
|
||||
}
|
||||
|
||||
SQLiteStmt::Use & SQLiteStmt::Use::operator () (const std::string & value, bool notNull)
|
||||
{
|
||||
if (notNull) {
|
||||
if (sqlite3_bind_text(stmt, curArg++, value.c_str(), -1, SQLITE_TRANSIENT) != SQLITE_OK)
|
||||
throwSQLiteError(stmt.db, "binding argument");
|
||||
} else
|
||||
bind();
|
||||
return *this;
|
||||
}
|
||||
|
||||
SQLiteStmt::Use & SQLiteStmt::Use::operator () (int64_t value, bool notNull)
|
||||
{
|
||||
if (notNull) {
|
||||
if (sqlite3_bind_int64(stmt, curArg++, value) != SQLITE_OK)
|
||||
throwSQLiteError(stmt.db, "binding argument");
|
||||
} else
|
||||
bind();
|
||||
return *this;
|
||||
}
|
||||
|
||||
SQLiteStmt::Use & SQLiteStmt::Use::bind()
|
||||
{
|
||||
if (sqlite3_bind_null(stmt, curArg++) != SQLITE_OK)
|
||||
throwSQLiteError(stmt.db, "binding argument");
|
||||
return *this;
|
||||
}
|
||||
|
||||
int SQLiteStmt::Use::step()
|
||||
{
|
||||
return sqlite3_step(stmt);
|
||||
}
|
||||
|
||||
void SQLiteStmt::Use::exec()
|
||||
{
|
||||
int r = step();
|
||||
assert(r != SQLITE_ROW);
|
||||
if (r != SQLITE_DONE)
|
||||
throwSQLiteError(stmt.db, "executing SQLite statement");
|
||||
}
|
||||
|
||||
bool SQLiteStmt::Use::next()
|
||||
{
|
||||
int r = step();
|
||||
if (r != SQLITE_DONE && r != SQLITE_ROW)
|
||||
throwSQLiteError(stmt.db, "executing SQLite query");
|
||||
return r == SQLITE_ROW;
|
||||
}
|
||||
|
||||
std::string SQLiteStmt::Use::getStr(int col)
|
||||
{
|
||||
auto s = (const char *) sqlite3_column_text(stmt, col);
|
||||
assert(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
int64_t SQLiteStmt::Use::getInt(int col)
|
||||
{
|
||||
// FIXME: detect nulls?
|
||||
return sqlite3_column_int64(stmt, col);
|
||||
}
|
||||
|
||||
SQLiteTxn::SQLiteTxn(sqlite3 * db)
|
||||
{
|
||||
this->db = db;
|
||||
if (sqlite3_exec(db, "begin;", 0, 0, 0) != SQLITE_OK)
|
||||
throwSQLiteError(db, "starting transaction");
|
||||
active = true;
|
||||
}
|
||||
|
||||
void SQLiteTxn::commit()
|
||||
{
|
||||
if (sqlite3_exec(db, "commit;", 0, 0, 0) != SQLITE_OK)
|
||||
throwSQLiteError(db, "committing transaction");
|
||||
active = false;
|
||||
}
|
||||
|
||||
SQLiteTxn::~SQLiteTxn()
|
||||
{
|
||||
try {
|
||||
if (active && sqlite3_exec(db, "rollback;", 0, 0, 0) != SQLITE_OK)
|
||||
throwSQLiteError(db, "aborting transaction");
|
||||
} catch (...) {
|
||||
ignoreException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
102
nix/libstore/sqlite.hh
Normal file
102
nix/libstore/sqlite.hh
Normal file
|
@ -0,0 +1,102 @@
|
|||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "types.hh"
|
||||
|
||||
class sqlite3;
|
||||
class sqlite3_stmt;
|
||||
|
||||
namespace nix {
|
||||
|
||||
/* RAII wrapper to close a SQLite database automatically. */
|
||||
struct SQLite
|
||||
{
|
||||
sqlite3 * db;
|
||||
SQLite() { db = 0; }
|
||||
~SQLite();
|
||||
operator sqlite3 * () { return db; }
|
||||
};
|
||||
|
||||
/* RAII wrapper to create and destroy SQLite prepared statements. */
|
||||
struct SQLiteStmt
|
||||
{
|
||||
sqlite3 * db = 0;
|
||||
sqlite3_stmt * stmt = 0;
|
||||
SQLiteStmt() { }
|
||||
void create(sqlite3 * db, const std::string & s);
|
||||
~SQLiteStmt();
|
||||
operator sqlite3_stmt * () { return stmt; }
|
||||
|
||||
/* Helper for binding / executing statements. */
|
||||
class Use
|
||||
{
|
||||
friend struct SQLiteStmt;
|
||||
private:
|
||||
SQLiteStmt & stmt;
|
||||
unsigned int curArg = 1;
|
||||
Use(SQLiteStmt & stmt);
|
||||
|
||||
public:
|
||||
|
||||
~Use();
|
||||
|
||||
/* Bind the next parameter. */
|
||||
Use & operator () (const std::string & value, bool notNull = true);
|
||||
Use & operator () (int64_t value, bool notNull = true);
|
||||
Use & bind(); // null
|
||||
|
||||
int step();
|
||||
|
||||
/* Execute a statement that does not return rows. */
|
||||
void exec();
|
||||
|
||||
/* For statements that return 0 or more rows. Returns true iff
|
||||
a row is available. */
|
||||
bool next();
|
||||
|
||||
std::string getStr(int col);
|
||||
int64_t getInt(int col);
|
||||
};
|
||||
|
||||
Use use()
|
||||
{
|
||||
return Use(*this);
|
||||
}
|
||||
};
|
||||
|
||||
/* RAII helper that ensures transactions are aborted unless explicitly
|
||||
committed. */
|
||||
struct SQLiteTxn
|
||||
{
|
||||
bool active = false;
|
||||
sqlite3 * db;
|
||||
|
||||
SQLiteTxn(sqlite3 * db);
|
||||
|
||||
void commit();
|
||||
|
||||
~SQLiteTxn();
|
||||
};
|
||||
|
||||
|
||||
MakeError(SQLiteError, Error);
|
||||
MakeError(SQLiteBusy, SQLiteError);
|
||||
|
||||
[[noreturn]] void throwSQLiteError(sqlite3 * db, const format & f);
|
||||
|
||||
/* Convenience function for retrying a SQLite transaction when the
|
||||
database is busy. */
|
||||
template<typename T>
|
||||
T retrySQLite(std::function<T()> fun)
|
||||
{
|
||||
while (true) {
|
||||
try {
|
||||
return fun();
|
||||
} catch (SQLiteBusy & e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -89,8 +89,8 @@ struct ValidPathInfo
|
|||
Hash hash;
|
||||
PathSet references;
|
||||
time_t registrationTime = 0;
|
||||
unsigned long long narSize = 0; // 0 = unknown
|
||||
unsigned long long id; // internal use only
|
||||
uint64_t narSize = 0; // 0 = unknown
|
||||
uint64_t id; // internal use only
|
||||
|
||||
bool operator == (const ValidPathInfo & i) const
|
||||
{
|
||||
|
|
|
@ -86,7 +86,8 @@ libstore_a_SOURCES = \
|
|||
%D%/libstore/local-store.cc \
|
||||
%D%/libstore/build.cc \
|
||||
%D%/libstore/pathlocks.cc \
|
||||
%D%/libstore/derivations.cc
|
||||
%D%/libstore/derivations.cc \
|
||||
%D%/libstore/sqlite.cc
|
||||
|
||||
libstore_headers = \
|
||||
%D%/libstore/references.hh \
|
||||
|
@ -96,6 +97,7 @@ libstore_headers = \
|
|||
%D%/libstore/derivations.hh \
|
||||
%D%/libstore/misc.hh \
|
||||
%D%/libstore/local-store.hh \
|
||||
%D%/libstore/sqlite.hh \
|
||||
%D%/libstore/store-api.hh
|
||||
|
||||
libstore_a_CPPFLAGS = \
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# GNU Guix --- Functional package management for GNU
|
||||
# Copyright © 2013, 2014 Ludovic Courtès <ludo@gnu.org>
|
||||
# Copyright © 2013, 2014, 2016 Ludovic Courtès <ludo@gnu.org>
|
||||
# Copyright © 2016 Jan Nieuwenhuizen <janneke@gnu.org>
|
||||
#
|
||||
# This file is part of GNU Guix.
|
||||
|
@ -27,6 +27,7 @@ tmpdir="guix-hash-$$"
|
|||
trap 'rm -rf "$tmpdir"' EXIT
|
||||
|
||||
test `guix hash /dev/null` = 0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73
|
||||
test `echo -n | guix hash -` = 0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73
|
||||
test `guix hash -f nix-base32 /dev/null` = 0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73
|
||||
test `guix hash -f hex /dev/null` = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||
test `guix hash -f base32 /dev/null` = 4oymiquy7qobjgx36tejs35zeqt24qpemsnzgtfeswmrw6csxbkq
|
||||
|
|
Loading…
Reference in a new issue