From 8dbfb1c4787628bca8ec72ce6d7f3c4780c07dc0 Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Thu, 26 Feb 2015 13:07:40 +0000 Subject: [PATCH] Add initial build files and enough code to launch a simple D-Bus daemon --- AUTHORS | 1 + MAINTAINERS | 1 + Makefile.am | 76 ++++++ NEWS | 0 README.md | 4 + autogen.sh | 28 ++ configure.ac | 117 +++++++++ contrib/fwupd.spec.in | 51 ++++ data/Makefile.am | 20 ++ data/org.freedesktop.fwupd.conf | 29 +++ data/org.freedesktop.fwupd.service.in | 4 + data/tests/Makefile.am | 5 + git.mk | 200 ++++++++++++++ m4/.gitignore | 1 + m4/as-linguas.m4 | 24 ++ m4/ax_check_compile_flag.m4 | 72 ++++++ m4/ax_check_link_flag.m4 | 71 +++++ man/Makefile.am | 26 ++ man/fwupdmgr.sgml | 113 ++++++++ po/.gitignore | 10 + po/POTFILES.in | 3 + po/en_GB.po | 25 ++ policy/Makefile.am | 12 + policy/org.freedesktop.fwupd.policy.in | 32 +++ src/Makefile.am | 89 +++++++ src/fu-cleanup.h | 91 +++++++ src/fu-common.h | 29 +++ src/fu-device.c | 173 +++++++++++++ src/fu-device.h | 63 +++++ src/fu-main.c | 327 +++++++++++++++++++++++ src/fu-provider-uefi.c | 148 +++++++++++ src/fu-provider-uefi.h | 65 +++++ src/fu-util.c | 345 +++++++++++++++++++++++++ src/fwupd.gresource.xml | 6 + src/org.freedesktop.fwupd.xml | 84 ++++++ 35 files changed, 2345 insertions(+) create mode 100644 AUTHORS create mode 100644 MAINTAINERS create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 README.md create mode 100755 autogen.sh create mode 100644 configure.ac create mode 100644 contrib/fwupd.spec.in create mode 100644 data/Makefile.am create mode 100644 data/org.freedesktop.fwupd.conf create mode 100644 data/org.freedesktop.fwupd.service.in create mode 100644 data/tests/Makefile.am create mode 100644 git.mk create mode 100644 m4/.gitignore create mode 100644 m4/as-linguas.m4 create mode 100644 m4/ax_check_compile_flag.m4 create mode 100644 m4/ax_check_link_flag.m4 create mode 100644 man/Makefile.am create mode 100644 man/fwupdmgr.sgml create mode 100644 po/.gitignore create mode 100644 po/POTFILES.in create mode 100644 po/en_GB.po create mode 100644 policy/Makefile.am create mode 100644 policy/org.freedesktop.fwupd.policy.in create mode 100644 src/Makefile.am create mode 100644 src/fu-cleanup.h create mode 100644 src/fu-common.h create mode 100644 src/fu-device.c create mode 100644 src/fu-device.h create mode 100644 src/fu-main.c create mode 100644 src/fu-provider-uefi.c create mode 100644 src/fu-provider-uefi.h create mode 100644 src/fu-util.c create mode 100644 src/fwupd.gresource.xml create mode 100644 src/org.freedesktop.fwupd.xml diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 000000000..026b70589 --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Richard Hughes diff --git a/MAINTAINERS b/MAINTAINERS new file mode 100644 index 000000000..026b70589 --- /dev/null +++ b/MAINTAINERS @@ -0,0 +1 @@ +Richard Hughes diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 000000000..7395b0779 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,76 @@ +AUTOMAKE_OPTIONS = 1.7 + +ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} + +SUBDIRS = \ + po \ + data \ + man \ + policy \ + src + +snapshot: + $(MAKE) dist distdir=$(PACKAGE)-$(VERSION)-`date +"%Y%m%d"` + +EXTRA_DIST = \ + COPYING \ + MAINTAINERS \ + AUTHORS \ + README.md \ + NEWS \ + autogen.sh \ + config.h \ + intltool-extract.in \ + intltool-merge.in \ + intltool-update.in + +MAINTAINERCLEANFILES = \ + $(srcdir)/INSTALL \ + $(srcdir)/ABOUT-NLS \ + $(srcdir)/aclocal.m4 \ + $(srcdir)/autoscan.log \ + $(srcdir)/compile \ + $(srcdir)/config.guess \ + $(srcdir)/config.rpath \ + $(srcdir)/config.h.in \ + $(srcdir)/config.sub \ + $(srcdir)/configure.scan \ + $(srcdir)/depcomp \ + $(srcdir)/install-sh \ + $(srcdir)/ltmain.sh \ + $(srcdir)/missing \ + $(srcdir)/mkinstalldirs \ + $(srcdir)/omf.make \ + $(srcdir)/test-driver \ + $(srcdir)/xmldocs.make \ + $(srcdir)/gtk-doc.make \ + $(srcdir)/ChangeLog \ + $(srcdir)/po/Makefile.in.in~ \ + $(srcdir)/fwupd-*.tar.* \ + `find "$(srcdir)" -type f -name Makefile.in -print` + +GITIGNOREFILES = \ + .tx + +distclean-local: + if test $(srdcir) = .; then :; else \ + rm -f ChangeLog; \ + fi + +ChangeLog: + @echo Creating $@ + @if test -d "$(srcdir)/.git"; then \ + (GIT_DIR=$(top_srcdir)/.git ./missing --run git log e197d80c8937c622f21f569457d1bbd05746d951.. --stat -M -C --name-status --date=short --no-color) | fmt --split-only > $@.tmp \ + && mv -f $@.tmp $@ \ + || ($(RM) $@.tmp; \ + echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \ + (test -f $@ || echo git-log is required to generate this file >> $@)); \ + else \ + test -f $@ || \ + (echo A git checkout and git-log is required to generate ChangeLog >&2 && \ + echo A git checkout and git-log is required to generate this file >> $@); \ + fi + +.PHONY: ChangeLog + +-include $(top_srcdir)/git.mk diff --git a/NEWS b/NEWS new file mode 100644 index 000000000..e69de29bb diff --git a/README.md b/README.md new file mode 100644 index 000000000..54ec09b01 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +fwupd +===== + +fwupd is a simple daemon to allow session software to update UEFI firmware. diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 000000000..bee1cd576 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,28 @@ +#!/bin/sh +# Copyright (C) 2015 Richard Hughes +# +# Run this to generate all the initial makefiles, etc. +# +# Licensed under the GNU General Public License Version 2 +# 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. + +test -n "$srcdir" || srcdir=`dirname "$0"` +test -n "$srcdir" || srcdir=. + +olddir=`pwd` +cd "$srcdir" + +AUTORECONF=`which autoreconf` +if test -z $AUTORECONF; then + echo "*** No autoreconf found, please install it ***" + exit 1 +fi + +autopoint --force +ACLOCAL="${ACLOCAL-aclocal} $ACLOCAL_FLAGS" AUTOPOINT='intltoolize --automake --copy' autoreconf --force --install --verbose + +cd "$olddir" +test -n "$NOCONFIGURE" || "$srcdir/configure" "$@" diff --git a/configure.ac b/configure.ac new file mode 100644 index 000000000..993a663a7 --- /dev/null +++ b/configure.ac @@ -0,0 +1,117 @@ +# Copyright (C) 2015 Richard Hughes +AC_PREREQ(2.63) + +AC_INIT([fwupd],[0.1.0],[http://www.freedesktop.org/software/fwupd/]) +AC_CONFIG_SRCDIR(src) +AM_INIT_AUTOMAKE([1.9 no-dist-gzip dist-xz tar-ustar foreign]) +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_MACRO_DIR([m4]) +AC_PROG_LIBTOOL + +m4_ifdef([GOBJECT_INTROSPECTION_CHECK], [GOBJECT_INTROSPECTION_CHECK([0.9.8])]) +AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$found_introspection" = xyes) +GLIB_GSETTINGS + +# enable nice build output on automake1.11 +m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) + +AS_ALL_LINGUAS +AC_PROG_CC +AC_PROG_INSTALL +LT_INIT +AM_PROG_CC_C_O +IT_PROG_INTLTOOL([0.35.0]) +AC_PATH_PROG(XSLTPROC, xsltproc) + +dnl --------------------------------------------------------------------------- +dnl - Extra verbose warning switches +dnl --------------------------------------------------------------------------- + +if test "$GCC" = "yes"; then + WARNINGFLAGS_C="$WARNINGFLAGS_C -Wall" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Wcast-align -Wno-uninitialized" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Wmissing-declarations" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Wpointer-arith" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Wcast-align" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Wwrite-strings" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Winit-self" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Wreturn-type" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Wformat-nonliteral" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Wformat-security" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Wmissing-include-dirs" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Wmissing-format-attribute" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Wclobbered" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Wempty-body" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Wignored-qualifiers" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Wsign-compare" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Wtype-limits" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Wuninitialized" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Waggregate-return" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Wdeclaration-after-statement" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Wshadow" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Wno-strict-aliasing" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Winline" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Wmissing-parameter-type" + WARNINGFLAGS_C="$WARNINGFLAGS_C -Woverride-init" +else + WARNINGFLAGS_C="" +fi +AC_SUBST(WARNINGFLAGS_C) + +dnl --------------------------------------------------------------------------- +dnl - gettext stuff +dnl --------------------------------------------------------------------------- +AM_GNU_GETTEXT_VERSION([0.17]) +AM_GNU_GETTEXT([external]) + +GETTEXT_PACKAGE=AC_PACKAGE_NAME +AC_SUBST(GETTEXT_PACKAGE) +AC_DEFINE(GETTEXT_PACKAGE, "AC_PACKAGE_NAME", [foo]) + +# check for PIE (position independent executable) support +if test x$with_pic != xno; then + AX_CHECK_COMPILE_FLAG([-fPIE], + [AX_CHECK_LINK_FLAG([-fPIE -pie], + [PIE_CFLAGS="-fPIE" PIE_LDFLAGS="-pie"])]) + AC_SUBST(PIE_CFLAGS) + AC_SUBST(PIE_LDFLAGS) +fi + +# check for full RELRO (relocation read-only) support +AX_CHECK_LINK_FLAG([-Wl,-z,relro,-z,now], + [RELRO_LDFLAGS="-Wl,-z,relro,-z,now"]) +AC_SUBST([RELRO_LDFLAGS]) + +dnl --------------------------------------------------------------------------- +dnl - Check library dependencies +dnl --------------------------------------------------------------------------- +PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.36.0 gobject-2.0 gthread-2.0 gio-2.0 >= 2.25.9 gio-unix-2.0) +PKG_CHECK_MODULES(GUDEV, gudev-1.0) +PKG_CHECK_MODULES(POLKIT, polkit-gobject-1 >= 0.103) +AC_PATH_PROG(DOCBOOK2MAN, docbook2man) + +dnl --------------------------------------------------------------------------- +dnl - Makefiles, etc. +dnl --------------------------------------------------------------------------- +AC_CONFIG_FILES([ +Makefile +man/Makefile +data/Makefile +data/tests/Makefile +policy/Makefile +po/Makefile.in +src/Makefile +]) +AC_OUTPUT + +dnl ========================================================================== +echo " + fwupd $VERSION + ================= + + prefix: ${prefix} + datadir: ${datadir} + compiler: ${CC} + cflags: ${CFLAGS} + cppflags: ${CPPFLAGS} +" diff --git a/contrib/fwupd.spec.in b/contrib/fwupd.spec.in new file mode 100644 index 000000000..e35720b6f --- /dev/null +++ b/contrib/fwupd.spec.in @@ -0,0 +1,51 @@ +%define alphatag #ALPHATAG# + +Summary: Firmware update daemon +Name: fwupd +Version: #VERSION# +Release: 0.#BUILD#%{?alphatag}%{?dist} +License: GPLv2+ +URL: https://github.com/hughsie/fwupd +Source0: http://www.freedesktop.org/software/releases/%{name}-%{version}.tar.xz + +BuildRequires: docbook-utils +BuildRequires: gettext +BuildRequires: glib2-devel +BuildRequires: intltool +BuildRequires: libgudev1-devel +BuildRequires: polkit-devel >= 0.103 + +%description +fwupd is a daemon to allow session software to update UEFI firmware. + +%prep +%setup -q + +%build +%configure \ + --disable-static \ + --disable-rpath \ + --disable-silent-rules \ + --disable-dependency-tracking + +make %{?_smp_mflags} + +%install +make install DESTDIR=$RPM_BUILD_ROOT + +%find_lang %{name} + +%files -f %{name}.lang +%doc README.md AUTHORS NEWS COPYING +%{_libexecdir}/fwupd +%{_bindir}/fwupdmgr +%{_sysconfdir}/dbus-1/system.d/org.freedesktop.fwupd.conf +%{_datadir}/dbus-1/interfaces/org.freedesktop.fwupd.xml +%{_datadir}/polkit-1/actions/org.freedesktop.fwupd.policy +%{_datadir}/dbus-1/system-services/org.freedesktop.fwupd.service +%{_datadir}/man/man1/fwupdmgr.1.gz + +%changelog +* #LONGDATE# Richard Hughes #VERSION#-0.#BUILD##ALPHATAG# +- Update from git + diff --git a/data/Makefile.am b/data/Makefile.am new file mode 100644 index 000000000..ffb901ebd --- /dev/null +++ b/data/Makefile.am @@ -0,0 +1,20 @@ +SUBDIRS = tests + +dbusdir = $(sysconfdir)/dbus-1/system.d +dist_dbus_DATA = org.freedesktop.fwupd.conf + +dbusservicemaindir = $(datadir)/dbus-1/system-services +dbusservicemain_in_files = org.freedesktop.fwupd.service.in +dbusservicemain_DATA = $(dbusservicemain_in_files:.service.in=.service) +$(dbusservicemain_DATA): $(dbusservicemain_in_files) Makefile + @sed -e "s|\@servicedir\@|$(libexecdir)|" $< | \ + sed -e "s|\@daemon_user\@|$(daemon_user)|" > $@ + +EXTRA_DIST = \ + $(dbusservicemain_in_files) + +DISTCLEANFILES = \ + $(dbusservicemain_DATA) \ + $(systemdservicemain_DATA) + +-include $(top_srcdir)/git.mk diff --git a/data/org.freedesktop.fwupd.conf b/data/org.freedesktop.fwupd.conf new file mode 100644 index 000000000..7267fa987 --- /dev/null +++ b/data/org.freedesktop.fwupd.conf @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/org.freedesktop.fwupd.service.in b/data/org.freedesktop.fwupd.service.in new file mode 100644 index 000000000..dfe0ddb19 --- /dev/null +++ b/data/org.freedesktop.fwupd.service.in @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=org.freedesktop.fwupd +Exec=@servicedir@/fwupd +#SystemdService=fwupd.service diff --git a/data/tests/Makefile.am b/data/tests/Makefile.am new file mode 100644 index 000000000..078960da6 --- /dev/null +++ b/data/tests/Makefile.am @@ -0,0 +1,5 @@ +test_files = + +EXTRA_DIST = $(test_files) + +-include $(top_srcdir)/git.mk diff --git a/git.mk b/git.mk new file mode 100644 index 000000000..abd6c0a28 --- /dev/null +++ b/git.mk @@ -0,0 +1,200 @@ +# git.mk +# +# Copyright 2009, Red Hat, Inc. +# Written by Behdad Esfahbod +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. +# +# The canonical source for this file is pango/git.mk, or whereever the +# header of pango/git.mk suggests in the future. +# +# To use in your project, import this file in your git repo's toplevel, +# then do "make -f git.mk". This modifies all Makefile.am files in +# your project to include git.mk. +# +# This enables automatic .gitignore generation. If you need to ignore +# more files, add them to the GITIGNOREFILES variable in your Makefile.am. +# But think twice before doing that. If a file has to be in .gitignore, +# chances are very high that it's a generated file and should be in one +# of MOSTLYCLEANFILES, CLEANFILES, DISTCLEANFILES, or MAINTAINERCLEANFILES. +# +# The only case that you need to manually add a file to GITIGNOREFILES is +# when remove files in one of mostlyclean-local, clean-local, distclean-local, +# or maintainer-clean-local. +# +# Note that for files like editor backup, etc, there are better places to +# ignore them. See "man gitignore". +# +# If "make maintainer-clean" removes the files but they are not recognized +# by this script (that is, if "git status" shows untracked files still), send +# me the output of "git status" as well as your Makefile.am and Makefile for +# the directories involved. +# +# For a list of toplevel files that should be in MAINTAINERCLEANFILES, see +# pango/Makefile.am. +# +# Don't EXTRA_DIST this file. It is supposed to only live in git clones, +# not tarballs. It serves no useful purpose in tarballs and clutters the +# build dir. +# +# This file knows how to handle autoconf, automake, libtool, gtk-doc, +# gnome-doc-utils, mallard, intltool, gsettings. +# +# +# KNOWN ISSUES: +# +# - Recursive configure doesn't work as $(top_srcdir)/git.mk inside the +# submodule doesn't find us. If you have configure.{in,ac} files in +# subdirs, add a proxy git.mk file in those dirs that simply does: +# "include $(top_srcdir)/../git.mk". Add more ..'s to your taste. +# And add those files to git. See vte/gnome-pty-helper/git.mk for +# example. +# +# ChangeLog +# +# - 2010-12-06 Add support for Mallard docs +# - 2010-12-06 Start this change log + +git-all: git-mk-install + +git-mk-install: + @echo Installing git makefile + @any_failed=; find $(top_srcdir) -name Makefile.am | while read x; do \ + if grep 'include .*/git.mk' $$x >/dev/null; then \ + echo $$x already includes git.mk; \ + else \ + failed=; \ + echo "Updating $$x"; \ + { cat $$x; \ + echo ''; \ + echo '-include $$(top_srcdir)/git.mk'; \ + } > $$x.tmp || failed=1; \ + if test x$$failed = x; then \ + mv $$x.tmp $$x || failed=1; \ + fi; \ + if test x$$failed = x; then : else \ + echo Failed updating $$x; >&2 \ + any_failed=1; \ + fi; \ + fi; done; test -z "$$any_failed" + +.PHONY: git-all git-mk-install + + +### .gitignore generation + +$(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk + $(AM_V_GEN) \ + { \ + if test "x$(DOC_MODULE)" = x -o "x$(DOC_MAIN_SGML_FILE)" = x; then :; else \ + for x in \ + $(DOC_MODULE)-decl-list.txt \ + $(DOC_MODULE)-decl.txt \ + tmpl/$(DOC_MODULE)-unused.sgml \ + "tmpl/*.bak" \ + xml html \ + ; do echo /$$x; done; \ + fi; \ + if test "x$(DOC_MODULE)$(DOC_ID)" = x -o "x$(DOC_LINGUAS)" = x; then :; else \ + for x in \ + $(_DOC_C_DOCS) \ + $(_DOC_LC_DOCS) \ + $(_DOC_OMF_ALL) \ + $(_DOC_DSK_ALL) \ + $(_DOC_HTML_ALL) \ + $(_DOC_MOFILES) \ + $(_DOC_POFILES) \ + $(DOC_H_FILE) \ + "*/.xml2po.mo" \ + "*/*.omf.out" \ + ; do echo /$$x; done; \ + fi; \ + if test "x$(gsettings_SCHEMAS)" = x; then :; else \ + for x in \ + $(gsettings_SCHEMAS:.xml=.valid) \ + $(gsettings__enum_file) \ + ; do echo /$$x; done; \ + fi; \ + if test -f $(srcdir)/po/Makefile.in.in; then \ + for x in \ + po/Makefile.in.in \ + po/Makefile.in \ + po/Makefile \ + po/POTFILES \ + po/stamp-it \ + po/.intltool-merge-cache \ + "po/*.gmo" \ + "po/*.mo" \ + po/$(GETTEXT_PACKAGE).pot \ + intltool-extract.in \ + intltool-merge.in \ + intltool-update.in \ + ; do echo /$$x; done; \ + fi; \ + if test -f $(srcdir)/configure; then \ + for x in \ + autom4te.cache \ + configure \ + config.h \ + stamp-h1 \ + libtool \ + config.lt \ + ; do echo /$$x; done; \ + fi; \ + for x in \ + .gitignore \ + $(GITIGNOREFILES) \ + $(CLEANFILES) \ + $(PROGRAMS) \ + $(check_PROGRAMS) \ + $(EXTRA_PROGRAMS) \ + $(LTLIBRARIES) \ + so_locations \ + .libs _libs \ + $(MOSTLYCLEANFILES) \ + "*.$(OBJEXT)" \ + "*.lo" \ + $(DISTCLEANFILES) \ + $(am__CONFIG_DISTCLEAN_FILES) \ + $(CONFIG_CLEAN_FILES) \ + TAGS ID GTAGS GRTAGS GSYMS GPATH tags \ + "*.tab.c" \ + $(MAINTAINERCLEANFILES) \ + $(BUILT_SOURCES) \ + $(DEPDIR) \ + Makefile \ + Makefile.in \ + "*.orig" \ + "*.rej" \ + "*.bak" \ + "*~" \ + ".*.sw[nop]" \ + ".dirstamp" \ + ; do echo /$$x; done; \ + } | \ + sed "s@^/`echo "$(srcdir)" | sed 's/\(.\)/[\1]/g'`/@/@" | \ + sed 's@/[.]/@/@g' | \ + LC_ALL=C sort | uniq > $@.tmp && \ + mv $@.tmp $@; + +all: $(srcdir)/.gitignore gitignore-recurse-maybe +gitignore-recurse-maybe: + @if test "x$(SUBDIRS)" = "x$(DIST_SUBDIRS)"; then :; else \ + $(MAKE) $(AM_MAKEFLAGS) gitignore-recurse; \ + fi; +gitignore-recurse: + @for subdir in $(DIST_SUBDIRS); do \ + case " $(SUBDIRS) " in \ + *" $$subdir "*) :;; \ + *) test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) .gitignore gitignore-recurse || echo "Skipping $$subdir");; \ + esac; \ + done +gitignore: $(srcdir)/.gitignore gitignore-recurse + +maintainer-clean: gitignore-clean +gitignore-clean: + -rm -f $(srcdir)/.gitignore + +.PHONY: gitignore-clean gitignore gitignore-recurse gitignore-recurse-maybe diff --git a/m4/.gitignore b/m4/.gitignore new file mode 100644 index 000000000..0f4126cd6 --- /dev/null +++ b/m4/.gitignore @@ -0,0 +1 @@ +*.m4 diff --git a/m4/as-linguas.m4 b/m4/as-linguas.m4 new file mode 100644 index 000000000..92b28f717 --- /dev/null +++ b/m4/as-linguas.m4 @@ -0,0 +1,24 @@ +# Set ALL_ALL_LINGUAS based on the .po files present. Optional argument is the +# name of the po directory. $podir/LINGUAS.ignore can be used to ignore a +# subset of the po files. + +AC_DEFUN([AS_ALL_LINGUAS], +[ + AC_MSG_CHECKING([for linguas]) + podir="m4_default([$1],[$srcdir/po])" + linguas=`cd $podir && ls *.po 2>/dev/null | awk 'BEGIN { FS="."; ORS=" " } { print $[]1 }'` + if test -f "$podir/LINGUAS.ignore"; then + ALL_LINGUAS=""; + ignore_linguas=`sed -n -e 's/^\s\+\|\s\+$//g' -e '/^#/b' -e '/\S/!b' \ + -e 's/\s\+/\n/g' -e p "$podir/LINGUAS.ignore"`; + for lang in $linguas; do + if ! echo "$ignore_linguas" | grep -q "^${lang}$"; then + ALL_LINGUAS="$ALL_LINGUAS $lang"; + fi; + done; + else + ALL_LINGUAS="$linguas"; + fi; + AC_SUBST([ALL_LINGUAS]) + AC_MSG_RESULT($ALL_LINGUAS) +]) diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4 new file mode 100644 index 000000000..c3a8d695a --- /dev/null +++ b/m4/ax_check_compile_flag.m4 @@ -0,0 +1,72 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the current language's compiler +# or gives an error. (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the current language's default +# flags (e.g. CFLAGS) when the check is done. The check is thus made with +# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to +# force the compiler to issue an error when a bad flag is given. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this +# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# 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 3 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 . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 2 + +AC_DEFUN([AX_CHECK_COMPILE_FLAG], +[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl +AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ + ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS + _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], + [AS_VAR_SET(CACHEVAR,[yes])], + [AS_VAR_SET(CACHEVAR,[no])]) + _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) +AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], + [m4_default([$2], :)], + [m4_default([$3], :)]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_COMPILE_FLAGS diff --git a/m4/ax_check_link_flag.m4 b/m4/ax_check_link_flag.m4 new file mode 100644 index 000000000..e2d0d363e --- /dev/null +++ b/m4/ax_check_link_flag.m4 @@ -0,0 +1,71 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the linker or gives an error. +# (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the linker's default flags +# when the check is done. The check is thus made with the flags: "LDFLAGS +# EXTRA-FLAGS FLAG". This can for example be used to force the linker to +# issue an error when a bad flag is given. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this +# macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# 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 3 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 . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 2 + +AC_DEFUN([AX_CHECK_LINK_FLAG], +[AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl +AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ + ax_check_save_flags=$LDFLAGS + LDFLAGS="$LDFLAGS $4 $1" + AC_LINK_IFELSE([AC_LANG_PROGRAM()], + [AS_VAR_SET(CACHEVAR,[yes])], + [AS_VAR_SET(CACHEVAR,[no])]) + LDFLAGS=$ax_check_save_flags]) +AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], + [m4_default([$2], :)], + [m4_default([$3], :)]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_LINK_FLAGS diff --git a/man/Makefile.am b/man/Makefile.am new file mode 100644 index 000000000..61ed68ec3 --- /dev/null +++ b/man/Makefile.am @@ -0,0 +1,26 @@ +man_MANS_DIST = \ + fwupdmgr.1 + +EXTRA_DIST = \ + fwupdmgr.sgml \ + $(man_MANS_DIST) + +man_MANS = \ + $(man_MANS_DIST) + +fwupdmgr.1: fwupdmgr.sgml + $(AM_V_GEN) \ + docbook2man $? > /dev/null + +MAINTAINERCLEANFILES = \ + manpage.links \ + manpage.log \ + manpage.refs \ + $(man_MANS) + +clean-local : + rm -f *~ + rm -f *.1 + rm -f manpage.* + +-include $(top_srcdir)/git.mk diff --git a/man/fwupdmgr.sgml b/man/fwupdmgr.sgml new file mode 100644 index 000000000..3423f058e --- /dev/null +++ b/man/fwupdmgr.sgml @@ -0,0 +1,113 @@ + + 26 February,2015"> + + GNU"> + GPL"> +]> + + + +
+ richard@hughsie.com; +
+ + Richard + Hughes + + + 2015 + Richard Hughes + + &date; +
+ + fwupdmgr + 1 + + + &package; + fwupd client tool + + + + &package; + + + + + DESCRIPTION + + This manual page documents briefly the &package; command. + + + &package; allows an administrator to update firmware. + + + + OPTIONS + + This program follows the usual &gnu; command line syntax, + with long options starting with two dashes (`-'). A summary of + options is included below. + + + + + + + + Show summary of options. + + + + + + COMMANDS + + This program takes commands with a variable number of arguments. + + + + + + + + Get the list of hardware that supports firmware updates. + + + + + + guid + filename + + + Install the update the next time the computer is rebooted. + + + + + + AUTHOR + This manual page was written by Richard Hughes richard@hughsie.com. + + +
+ + diff --git a/po/.gitignore b/po/.gitignore new file mode 100644 index 000000000..7e78a29b4 --- /dev/null +++ b/po/.gitignore @@ -0,0 +1,10 @@ +*.gmo +*.header +.intltool-merge-cache +Makefile.in.in +Makevars.template +POTFILES +Rules-quot +*.sed +*.sin +stamp-it diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 000000000..5f1edc3fe --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,3 @@ +policy/org.freedesktop.fwupd.policy.in +src/fu-main.c +src/fu-util.c diff --git a/po/en_GB.po b/po/en_GB.po new file mode 100644 index 000000000..2fffc2e93 --- /dev/null +++ b/po/en_GB.po @@ -0,0 +1,25 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Richard Hughes , 2015 +# Robert Readman , 2013 +msgid "" +msgstr "" +"Project-Id-Version: fwupd\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-11-10 11:04+0000\n" +"PO-Revision-Date: 2014-11-10 11:04+0000\n" +"Last-Translator: Richard Hughes \n" +"Language-Team: English (United Kingdom) (http://www.transifex.com/projects/p/colord/language/en_GB/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_GB\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. TRANSLATORS: this is a command alias +#, c-format +msgid "Alias to %s" +msgstr "Alias to %s" diff --git a/policy/Makefile.am b/policy/Makefile.am new file mode 100644 index 000000000..79d06d0f0 --- /dev/null +++ b/policy/Makefile.am @@ -0,0 +1,12 @@ +@INTLTOOL_POLICY_RULE@ +polkit_policydir = $(datadir)/polkit-1/actions +polkit_policy_in_files = org.freedesktop.fwupd.policy.in +polkit_policy_DATA = $(polkit_policy_in_files:.policy.in=.policy) +#polkit_policy_DATA = \ +# org.freedesktop.fwupd.policy + +EXTRA_DIST = org.freedesktop.fwupd.policy.in +CLEANFILES = \ + org.freedesktop.fwupd.policy + +-include $(top_srcdir)/git.mk diff --git a/policy/org.freedesktop.fwupd.policy.in b/policy/org.freedesktop.fwupd.policy.in new file mode 100644 index 000000000..1cfc9cb6f --- /dev/null +++ b/policy/org.freedesktop.fwupd.policy.in @@ -0,0 +1,32 @@ + + + + + + + System firmware update + https://github.com/hughsie/fwupd + application-vnd.iccprofile + + + + <_description>Install system firmware update + <_message>Authentication is required to update the firmware on this machine + application-vnd.iccprofile + + auth_admin + no + auth_admin_keep + + + + diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 000000000..21df31d5c --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,89 @@ +introspectiondir = $(datadir)/dbus-1/interfaces +dist_introspection_DATA = \ + org.freedesktop.fwupd.xml + +AM_CPPFLAGS = \ + $(PIE_CFLAGS) \ + $(GLIB_CFLAGS) \ + $(POLKIT_CFLAGS) \ + $(GUDEV_CFLAGS) \ + -DG_LOG_DOMAIN=\"Fu\" \ + -DLIBEXECDIR=\"$(libexecdir)\" \ + -DLIBDIR=\"$(libdir)\" \ + -DDATADIR=\"$(datadir)\" \ + -DSYSCONFDIR=\""$(sysconfdir)"\" \ + -DLOCALSTATEDIR=\""$(localstatedir)"\" \ + -DVERSION="\"$(VERSION)\"" \ + -DDAEMON_USER="\"$(daemon_user)\"" \ + -DG_UDEV_API_IS_SUBJECT_TO_CHANGE \ + -DLOCALEDIR=\""$(localedir)"\" + +bin_PROGRAMS = fwupdmgr + +fwupdmgr_SOURCES = \ + fu-util.c + +fwupdmgr_LDADD = \ + $(GLIB_LIBS) + +fwupdmgr_LDFLAGS = \ + $(PIE_LDFLAGS) + +fwupdmgr_CFLAGS = \ + $(WARNINGFLAGS_C) + +fu-resources.c: fwupd.gresource.xml $(dist_introspection_DATA) + $(AM_V_GEN) \ + glib-compile-resources \ + --sourcedir=$(srcdir) \ + --sourcedir=$(top_builddir)/data \ + --target=$@ \ + --generate-source \ + --c-name fu \ + $(srcdir)/fwupd.gresource.xml +fu-resources.h: fwupd.gresource.xml + $(AM_V_GEN) \ + glib-compile-resources \ + --sourcedir=$(srcdir) \ + --sourcedir=$(top_builddir)/data \ + --target=$@ \ + --generate-header \ + --c-name fu \ + $(srcdir)/fwupd.gresource.xml + +libexec_PROGRAMS = \ + fwupd + +fwupd_SOURCES = \ + fu-cleanup.h \ + fu-common.h \ + fu-device.c \ + fu-device.h \ + fu-provider-uefi.c \ + fu-provider-uefi.h \ + fu-resources.c \ + fu-resources.h \ + fu-main.c + +fwupd_LDADD = \ + $(POLKIT_LIBS) \ + $(GUDEV_LIBS) \ + $(GLIB_LIBS) + +fwupd_LDFLAGS = \ + $(PIE_LDFLAGS) \ + $(RELRO_LDFLAGS) + +fwupd_CFLAGS = \ + $(WARNINGFLAGS_C) + +BUILT_SOURCES = \ + fu-resources.c \ + fu-resources.h + +CLEANFILES = $(BUILT_SOURCES) *.log *.trs + +EXTRA_DIST = \ + fwupd.gresource.xml + +-include $(top_srcdir)/git.mk diff --git a/src/fu-cleanup.h b/src/fu-cleanup.h new file mode 100644 index 000000000..5f8bd427c --- /dev/null +++ b/src/fu-cleanup.h @@ -0,0 +1,91 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2012 Colin Walters . + * Copyright (C) 2014-2015 Richard Hughes + * + * Licensed under the GNU Lesser General Public License Version 2.1 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __FU_CLEANUP_H__ +#define __FU_CLEANUP_H__ + +#include + +G_BEGIN_DECLS + +#define GS_DEFINE_CLEANUP_FUNCTION(Type, name, func) \ + static inline void name (void *v) \ + { \ + func (*(Type*)v); \ + } + +#define GS_DEFINE_CLEANUP_FUNCTION0(Type, name, func) \ + static inline void name (void *v) \ + { \ + if (*(Type*)v) \ + func (*(Type*)v); \ + } + +#define GS_DEFINE_CLEANUP_FUNCTIONt(Type, name, func) \ + static inline void name (void *v) \ + { \ + if (*(Type*)v) \ + func (*(Type*)v, TRUE); \ + } + +GS_DEFINE_CLEANUP_FUNCTION0(GArray*, gs_local_array_unref, g_array_unref) +GS_DEFINE_CLEANUP_FUNCTION0(GBytes*, gs_local_bytes_unref, g_bytes_unref) +GS_DEFINE_CLEANUP_FUNCTION0(GChecksum*, gs_local_checksum_free, g_checksum_free) +GS_DEFINE_CLEANUP_FUNCTION0(GDir*, gs_local_dir_close, g_dir_close) +GS_DEFINE_CLEANUP_FUNCTION0(GError*, gs_local_free_error, g_error_free) +GS_DEFINE_CLEANUP_FUNCTION0(GHashTable*, gs_local_hashtable_unref, g_hash_table_unref) +GS_DEFINE_CLEANUP_FUNCTION0(GKeyFile*, gs_local_keyfile_unref, g_key_file_unref) +GS_DEFINE_CLEANUP_FUNCTION0(GMarkupParseContext*, gs_local_markup_parse_context_unref, g_markup_parse_context_unref) +GS_DEFINE_CLEANUP_FUNCTION0(GObject*, gs_local_obj_unref, g_object_unref) +GS_DEFINE_CLEANUP_FUNCTION0(GPtrArray*, gs_local_ptrarray_unref, g_ptr_array_unref) +GS_DEFINE_CLEANUP_FUNCTION0(GTimer*, gs_local_destroy_timer, g_timer_destroy) +GS_DEFINE_CLEANUP_FUNCTION0(GVariantBuilder*, gs_local_variant_builder_unref, g_variant_builder_unref) +GS_DEFINE_CLEANUP_FUNCTION0(GVariant*, gs_local_variant_unref, g_variant_unref) +GS_DEFINE_CLEANUP_FUNCTION0(GVariantIter*, gs_local_variant_iter_free, g_variant_iter_free) + +GS_DEFINE_CLEANUP_FUNCTIONt(GString*, gs_local_free_string, g_string_free) + +GS_DEFINE_CLEANUP_FUNCTION(char**, gs_local_strfreev, g_strfreev) +GS_DEFINE_CLEANUP_FUNCTION(GList*, gs_local_free_list, g_list_free) +GS_DEFINE_CLEANUP_FUNCTION(void*, gs_local_free, g_free) + +#define _cleanup_dir_close_ __attribute__ ((cleanup(gs_local_dir_close))) +#define _cleanup_timer_destroy_ __attribute__ ((cleanup(gs_local_destroy_timer))) +#define _cleanup_free_ __attribute__ ((cleanup(gs_local_free))) +#define _cleanup_checksum_free_ __attribute__ ((cleanup(gs_local_checksum_free))) +#define _cleanup_error_free_ __attribute__ ((cleanup(gs_local_free_error))) +#define _cleanup_list_free_ __attribute__ ((cleanup(gs_local_free_list))) +#define _cleanup_string_free_ __attribute__ ((cleanup(gs_local_free_string))) +#define _cleanup_strv_free_ __attribute__ ((cleanup(gs_local_strfreev))) +#define _cleanup_variant_iter_free_ __attribute__ ((cleanup(gs_local_variant_iter_free))) +#define _cleanup_array_unref_ __attribute__ ((cleanup(gs_local_array_unref))) +#define _cleanup_bytes_unref_ __attribute__ ((cleanup(gs_local_bytes_unref))) +#define _cleanup_hashtable_unref_ __attribute__ ((cleanup(gs_local_hashtable_unref))) +#define _cleanup_keyfile_unref_ __attribute__ ((cleanup(gs_local_keyfile_unref))) +#define _cleanup_markup_parse_context_unref_ __attribute__ ((cleanup(gs_local_markup_parse_context_unref))) +#define _cleanup_object_unref_ __attribute__ ((cleanup(gs_local_obj_unref))) +#define _cleanup_ptrarray_unref_ __attribute__ ((cleanup(gs_local_ptrarray_unref))) +#define _cleanup_variant_unref_ __attribute__ ((cleanup(gs_local_variant_unref))) + +G_END_DECLS + +#endif diff --git a/src/fu-common.h b/src/fu-common.h new file mode 100644 index 000000000..449ec1bec --- /dev/null +++ b/src/fu-common.h @@ -0,0 +1,29 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2015 Richard Hughes + * + * Licensed under the GNU General Public License Version 2 + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef __FU_COMMON_H +#define __FU_COMMON_H + +#define FWUPD_DBUS_PATH "/" +#define FWUPD_DBUS_SERVICE "org.freedesktop.fwupd" +#define FWUPD_DBUS_INTERFACE "org.freedesktop.fwupd" + +#endif /* __FU_COMMON_H */ diff --git a/src/fu-device.c b/src/fu-device.c new file mode 100644 index 000000000..a5e5feb9d --- /dev/null +++ b/src/fu-device.c @@ -0,0 +1,173 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2015 Richard Hughes + * + * Licensed under the GNU General Public License Version 2 + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include +#include + +#include "fu-cleanup.h" +#include "fu-common.h" +#include "fu-device.h" + +static void fu_device_finalize (GObject *object); + +#define FU_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), FU_TYPE_DEVICE, FuDevicePrivate)) + +/** + * FuDevicePrivate: + * + * Private #FuDevice data + **/ +struct _FuDevicePrivate +{ + gchar *id; +}; + +enum { + SIGNAL_LAST +}; + +enum { + PROP_0, + PROP_ID, + PROP_LAST +}; + +G_DEFINE_TYPE (FuDevice, fu_device, G_TYPE_OBJECT) + +/** + * fu_device_get_id: + **/ +const gchar * +fu_device_get_id (FuDevice *device) +{ + g_return_val_if_fail (FU_IS_DEVICE (device), NULL); + return device->priv->id; +} + +/** + * fu_device_set_id: + **/ +void +fu_device_set_id (FuDevice *device, const gchar *id) +{ + g_return_if_fail (FU_IS_DEVICE (device)); + + g_free (device->priv->id); + device->priv->id = g_strdup (id); +} + +/** + * fu_device_get_property: + **/ +static void +fu_device_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + FuDevice *device = FU_DEVICE (object); + FuDevicePrivate *priv = device->priv; + + switch (prop_id) { + case PROP_ID: + g_value_set_string (value, priv->id); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * fu_device_set_property: + **/ +static void +fu_device_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + FuDevice *device = FU_DEVICE (object); + FuDevicePrivate *priv = device->priv; + + switch (prop_id) { + case PROP_ID: + g_free (priv->id); + priv->id = g_strdup (g_value_get_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * fu_device_class_init: + **/ +static void +fu_device_class_init (FuDeviceClass *klass) +{ + GParamSpec *pspec; + GObjectClass *object_class = G_OBJECT_CLASS (klass); + object_class->finalize = fu_device_finalize; + object_class->get_property = fu_device_get_property; + object_class->set_property = fu_device_set_property; + + /** + * FuDevice:id: + */ + pspec = g_param_spec_string ("id", NULL, NULL, + NULL, + G_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_ID, pspec); + + g_type_class_add_private (klass, sizeof (FuDevicePrivate)); +} + +/** + * fu_device_init: + **/ +static void +fu_device_init (FuDevice *device) +{ + device->priv = FU_DEVICE_GET_PRIVATE (device); +} + +/** + * fu_device_finalize: + **/ +static void +fu_device_finalize (GObject *object) +{ + FuDevice *device = FU_DEVICE (object); + FuDevicePrivate *priv = device->priv; + + g_free (priv->id); + + G_OBJECT_CLASS (fu_device_parent_class)->finalize (object); +} + +/** + * fu_device_new: + **/ +FuDevice * +fu_device_new (void) +{ + FuDevice *device; + device = g_object_new (FU_TYPE_DEVICE, NULL); + return FU_DEVICE (device); +} diff --git a/src/fu-device.h b/src/fu-device.h new file mode 100644 index 000000000..ccd1468c6 --- /dev/null +++ b/src/fu-device.h @@ -0,0 +1,63 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2015 Richard Hughes + * + * Licensed under the GNU General Public License Version 2 + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef __FU_DEVICE_H +#define __FU_DEVICE_H + +#include + +G_BEGIN_DECLS + +#define FU_TYPE_DEVICE (fu_device_get_type ()) +#define FU_DEVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), FU_TYPE_DEVICE, FuDevice)) +#define FU_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), FU_TYPE_DEVICE, FuDeviceClass)) +#define FU_IS_DEVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), FU_TYPE_DEVICE)) +#define FU_IS_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), FU_TYPE_DEVICE)) +#define FU_DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), FU_TYPE_DEVICE, FuDeviceClass)) +#define FU_DEVICE_ERROR fu_device_error_quark() + +typedef struct _FuDevicePrivate FuDevicePrivate; +typedef struct _FuDevice FuDevice; +typedef struct _FuDeviceClass FuDeviceClass; + +struct _FuDevice +{ + GObject parent; + FuDevicePrivate *priv; +}; + +struct _FuDeviceClass +{ + GObjectClass parent_class; +}; + +GType fu_device_get_type (void); +FuDevice *fu_device_new (void); + +/* accessors */ +const gchar *fu_device_get_id (FuDevice *device); +void fu_device_set_id (FuDevice *device, + const gchar *id); + +G_END_DECLS + +#endif /* __FU_DEVICE_H */ + diff --git a/src/fu-main.c b/src/fu-main.c new file mode 100644 index 000000000..24692c05e --- /dev/null +++ b/src/fu-main.c @@ -0,0 +1,327 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2015 Richard Hughes + * + * Licensed under the GNU General Public License Version 2 + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "fu-cleanup.h" +#include "fu-common.h" +#include "fu-device.h" +#include "fu-provider-uefi.h" +#include "fu-resources.h" + +#define FU_ERROR 1 +#define FU_ERROR_INTERNAL 0 + +typedef struct { + GDBusConnection *connection; + GDBusNodeInfo *introspection_daemon; + GMainLoop *loop; + GPtrArray *devices; + FuProviderUefi *provider_uefi; +} FuMainPrivate; + +/** + * fu_main_get_device_list_as_strv: + **/ +static gchar ** +fu_main_get_device_list_as_strv (FuMainPrivate *priv) +{ + gchar **val; + guint i; + FuDevice *dev_tmp; + + val = g_new0 (gchar *, priv->devices->len + 1); + for (i = 0; i < priv->devices->len; i++) { + dev_tmp = g_ptr_array_index (priv->devices, i); + val[i] = g_strdup (fu_device_get_id (dev_tmp)); + } + return val; +} + +/** + * fu_main_daemon_method_call: + **/ +static void +fu_main_daemon_method_call (GDBusConnection *connection, const gchar *sender, + const gchar *object_path, const gchar *interface_name, + const gchar *method_name, GVariant *parameters, + GDBusMethodInvocation *invocation, gpointer user_data) +{ + FuMainPrivate *priv = (FuMainPrivate *) user_data; + GVariant *val; + + /* return 'as' */ + if (g_strcmp0 (method_name, "GetDevices") == 0) { + _cleanup_strv_free_ gchar **devices = NULL; + devices = fu_main_get_device_list_as_strv (priv); + val = g_variant_new ("(^as)", devices); + g_dbus_method_invocation_return_value (invocation, val); + return; + } + + /* we suck */ + g_dbus_method_invocation_return_error (invocation, + FU_ERROR, + FU_ERROR_INTERNAL, + "no such method %s", + method_name); +} + +/** + * fu_main_daemon_get_property: + **/ +static GVariant * +fu_main_daemon_get_property (GDBusConnection *connection_, const gchar *sender, + const gchar *object_path, const gchar *interface_name, + const gchar *property_name, GError **error, + gpointer user_data) +{ + if (g_strcmp0 (property_name, "DaemonVersion") == 0) + return g_variant_new_string (VERSION); + + /* return an error */ + g_set_error (error, + FU_ERROR, + FU_ERROR_INTERNAL, + "failed to get daemon property %s", + property_name); + return NULL; +} + +/** + * fu_main_on_bus_acquired_cb: + **/ +static void +fu_main_on_bus_acquired_cb (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + FuMainPrivate *priv = (FuMainPrivate *) user_data; + guint registration_id; + static const GDBusInterfaceVTable interface_vtable = { + fu_main_daemon_method_call, + fu_main_daemon_get_property, + NULL + }; + + priv->connection = g_object_ref (connection); + registration_id = g_dbus_connection_register_object (connection, + FWUPD_DBUS_PATH, + priv->introspection_daemon->interfaces[0], + &interface_vtable, + priv, /* user_data */ + NULL, /* user_data_free_func */ + NULL); /* GError** */ + g_assert (registration_id > 0); +} + +/** + * fu_main_on_name_acquired_cb: + **/ +static void +fu_main_on_name_acquired_cb (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + FuMainPrivate *priv = (FuMainPrivate *) user_data; + fu_provider_uefi_coldplug (priv->provider_uefi); + g_debug ("FuMain: acquired name: %s", name); +} + +/** + * fu_main_on_name_lost_cb: + **/ +static void +fu_main_on_name_lost_cb (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + FuMainPrivate *priv = (FuMainPrivate *) user_data; + g_debug ("FuMain: lost name: %s", name); + g_main_loop_quit (priv->loop); +} + +/** + * fu_main_timed_exit_cb: + **/ +static gboolean +fu_main_timed_exit_cb (gpointer user_data) +{ + GMainLoop *loop = (GMainLoop *) user_data; + g_main_loop_quit (loop); + return G_SOURCE_REMOVE; +} + +/** + * fu_main_load_introspection: + **/ +static GDBusNodeInfo * +fu_main_load_introspection (const gchar *filename, GError **error) +{ + _cleanup_bytes_unref_ GBytes *data = NULL; + _cleanup_free_ gchar *path = NULL; + + /* lookup data */ + path = g_build_filename ("/org/freedesktop/fwupd", filename, NULL); + data = g_resource_lookup_data (fu_get_resource (), + path, + G_RESOURCE_LOOKUP_FLAGS_NONE, + error); + if (data == NULL) + return NULL; + + /* build introspection from XML */ + return g_dbus_node_info_new_for_xml (g_bytes_get_data (data, NULL), error); +} + +/** + * cd_main_provider_device_added_cb: + **/ +static void +cd_main_provider_device_added_cb (FuProviderUefi *provider_uefi, + FuDevice *device, + gpointer user_data) +{ + FuMainPrivate *priv = (FuMainPrivate *) user_data; + g_ptr_array_add (priv->devices, g_object_ref (device)); +} + +/** + * cd_main_provider_device_removed_cb: + **/ +static void +cd_main_provider_device_removed_cb (FuProviderUefi *provider_uefi, + FuDevice *device, + gpointer user_data) +{ + FuMainPrivate *priv = (FuMainPrivate *) user_data; + g_ptr_array_remove (priv->devices, g_object_ref (device)); +} + +/** + * main: + **/ +int +main (int argc, char *argv[]) +{ + FuMainPrivate *priv = NULL; + gboolean immediate_exit = FALSE; + gboolean ret; + gboolean timed_exit = FALSE; + GOptionContext *context; + guint owner_id = 0; + guint retval = 1; + const GOptionEntry options[] = { + { "timed-exit", '\0', 0, G_OPTION_ARG_NONE, &timed_exit, + /* TRANSLATORS: exit after we've started up, used for user profiling */ + _("Exit after a small delay"), NULL }, + { "immediate-exit", '\0', 0, G_OPTION_ARG_NONE, &immediate_exit, + /* TRANSLATORS: exit straight away, used for automatic profiling */ + _("Exit after the engine has loaded"), NULL }, + { NULL} + }; + _cleanup_error_free_ GError *error = NULL; + + setlocale (LC_ALL, ""); + + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); + + /* TRANSLATORS: program name */ + g_set_application_name (_("Firmware Update")); + context = g_option_context_new (NULL); + g_option_context_add_main_entries (context, options, NULL); + g_option_context_set_summary (context, _("Firmware Update D-Bus Service")); + ret = g_option_context_parse (context, &argc, &argv, &error); + if (!ret) { + g_warning ("FuMain: failed to parse command line arguments: %s", + error->message); + goto out; + } + + /* create new objects */ + priv = g_new0 (FuMainPrivate, 1); + priv->devices = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); + priv->loop = g_main_loop_new (NULL, FALSE); + priv->provider_uefi = fu_provider_uefi_new (); + g_signal_connect (priv->provider_uefi, "device-added", + G_CALLBACK (cd_main_provider_device_added_cb), + priv); + g_signal_connect (priv->provider_uefi, "device-removed", + G_CALLBACK (cd_main_provider_device_removed_cb), + priv); + + /* load introspection from file */ + priv->introspection_daemon = fu_main_load_introspection (FWUPD_DBUS_INTERFACE ".xml", + &error); + if (priv->introspection_daemon == NULL) { + g_warning ("FuMain: failed to load daemon introspection: %s", + error->message); + goto out; + } + + /* own the object */ + owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM, + FWUPD_DBUS_SERVICE, + G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | + G_BUS_NAME_OWNER_FLAGS_REPLACE, + fu_main_on_bus_acquired_cb, + fu_main_on_name_acquired_cb, + fu_main_on_name_lost_cb, + priv, NULL); + + /* Only timeout and close the mainloop if we have specified it + * on the command line */ + if (immediate_exit) + g_idle_add (fu_main_timed_exit_cb, priv->loop); + else if (timed_exit) + g_timeout_add_seconds (5, fu_main_timed_exit_cb, priv->loop); + + /* wait */ + g_info ("Daemon ready for requests"); + g_main_loop_run (priv->loop); + + /* success */ + retval = 0; +out: + g_option_context_free (context); + if (owner_id > 0) + g_bus_unown_name (owner_id); + if (priv != NULL) { + if (priv->loop != NULL) + g_main_loop_unref (priv->loop); + if (priv->connection != NULL) + g_object_unref (priv->connection); + if (priv->introspection_daemon != NULL) + g_dbus_node_info_unref (priv->introspection_daemon); + g_ptr_array_unref (priv->devices); + g_free (priv); + } + return retval; +} + diff --git a/src/fu-provider-uefi.c b/src/fu-provider-uefi.c new file mode 100644 index 000000000..f57fef2c5 --- /dev/null +++ b/src/fu-provider-uefi.c @@ -0,0 +1,148 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2015 Richard Hughes + * + * Licensed under the GNU General Public License Version 2 + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include +#include + +#include "fu-cleanup.h" +#include "fu-device.h" +#include "fu-provider-uefi.h" + +static void fu_provider_uefi_finalize (GObject *object); + +#define FU_PROVIDER_UEFI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), FU_TYPE_PROVIDER_UEFI, FuProviderUefiPrivate)) + +/** + * FuProviderUefiPrivate: + **/ +struct _FuProviderUefiPrivate +{ + GPtrArray *array_devices; +}; + +enum { + SIGNAL_SENSOR_ADDED, + SIGNAL_SENSOR_REMOVED, + SIGNAL_LAST +}; + +static guint signals[SIGNAL_LAST] = { 0 }; + +G_DEFINE_TYPE (FuProviderUefi, fu_provider_uefi, G_TYPE_OBJECT) + +/** + * fu_provider_uefi_get_by_id: + **/ +static FuDevice * +fu_provider_uefi_get_by_id (FuProviderUefi *provider_uefi, + const gchar *device_id) +{ + FuProviderUefiPrivate *priv = provider_uefi->priv; + FuDevice *device = NULL; + FuDevice *device_tmp; + guint i; + + for (i = 0; i < priv->array_devices->len; i++) { + device_tmp = g_ptr_array_index (priv->array_devices, i); + if (g_strcmp0 (fu_device_get_id (device_tmp), device_id) == 0) { + device = g_object_ref (device_tmp); + break; + } + } + return device; +} + +/** + * fu_provider_uefi_coldplug: + **/ +void +fu_provider_uefi_coldplug (FuProviderUefi *provider_uefi) +{ + _cleanup_object_unref_ FuDevice *dev = NULL; + + //FIXME + g_debug ("Adding fake UEFI device"); + dev = fu_device_new (); + fu_device_set_id (dev, "819b858e-c52c-402f-80e1-5b311b6c1959"); + g_signal_emit (provider_uefi, signals[SIGNAL_SENSOR_ADDED], 0, dev); +} + +/** + * fu_provider_uefi_class_init: + **/ +static void +fu_provider_uefi_class_init (FuProviderUefiClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + object_class->finalize = fu_provider_uefi_finalize; + signals[SIGNAL_SENSOR_ADDED] = + g_signal_new ("device-added", + G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (FuProviderUefiClass, device_added), + NULL, NULL, g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, FU_TYPE_DEVICE); + signals[SIGNAL_SENSOR_REMOVED] = + g_signal_new ("device-removed", + G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (FuProviderUefiClass, device_removed), + NULL, NULL, g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, FU_TYPE_DEVICE); + + g_type_class_add_private (klass, sizeof (FuProviderUefiPrivate)); +} + +/** + * fu_provider_uefi_init: + **/ +static void +fu_provider_uefi_init (FuProviderUefi *provider_uefi) +{ + provider_uefi->priv = FU_PROVIDER_UEFI_GET_PRIVATE (provider_uefi); + provider_uefi->priv->array_devices = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); +} + +/** + * fu_provider_uefi_finalize: + **/ +static void +fu_provider_uefi_finalize (GObject *object) +{ + FuProviderUefi *provider_uefi = FU_PROVIDER_UEFI (object); + FuProviderUefiPrivate *priv = provider_uefi->priv; + + g_ptr_array_unref (priv->array_devices); + + G_OBJECT_CLASS (fu_provider_uefi_parent_class)->finalize (object); +} + +/** + * fu_provider_uefi_new: + **/ +FuProviderUefi * +fu_provider_uefi_new (void) +{ + FuProviderUefi *provider_uefi; + provider_uefi = g_object_new (FU_TYPE_PROVIDER_UEFI, NULL); + return FU_PROVIDER_UEFI (provider_uefi); +} + diff --git a/src/fu-provider-uefi.h b/src/fu-provider-uefi.h new file mode 100644 index 000000000..e45004491 --- /dev/null +++ b/src/fu-provider-uefi.h @@ -0,0 +1,65 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2015 Richard Hughes + * + * Licensed under the GNU General Public License Version 2 + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef __FU_PROVIDER_UEFI_H +#define __FU_PROVIDER_UEFI_H + +#include + +#include "fu-device.h" +#include "fu-provider-uefi.h" + +G_BEGIN_DECLS + +#define FU_TYPE_PROVIDER_UEFI (fu_provider_uefi_get_type ()) +#define FU_PROVIDER_UEFI(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), FU_TYPE_PROVIDER_UEFI, FuProviderUefi)) +#define FU_PROVIDER_UEFI_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), FU_TYPE_PROVIDER_UEFI, FuProviderUefiClass)) +#define FU_IS_PROVIDER_UEFI(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), FU_TYPE_PROVIDER_UEFI)) +#define FU_IS_PROVIDER_UEFI_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), FU_TYPE_PROVIDER_UEFI)) +#define FU_PROVIDER_UEFI_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), FU_TYPE_PROVIDER_UEFI, FuProviderUefiClass)) + +typedef struct _FuProviderUefiPrivate FuProviderUefiPrivate; +typedef struct _FuProviderUefi FuProviderUefi; +typedef struct _FuProviderUefiClass FuProviderUefiClass; + +struct _FuProviderUefi +{ + GObject parent; + FuProviderUefiPrivate *priv; +}; + +struct _FuProviderUefiClass +{ + GObjectClass parent_class; + void (* device_added) (FuProviderUefi *provider_uefi, + FuDevice *device); + void (* device_removed) (FuProviderUefi *provider_uefi, + FuDevice *device); +}; + +GType fu_provider_uefi_get_type (void); +FuProviderUefi *fu_provider_uefi_new (void); +void fu_provider_uefi_coldplug (FuProviderUefi *provider_uefi); + +G_END_DECLS + +#endif /* __FU_PROVIDER_UEFI_H */ + diff --git a/src/fu-util.c b/src/fu-util.c new file mode 100644 index 000000000..ad4daf72f --- /dev/null +++ b/src/fu-util.c @@ -0,0 +1,345 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2015 Richard Hughes + * + * Licensed under the GNU General Public License Version 2 + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "fu-cleanup.h" +#include "fu-common.h" + +#define FU_ERROR 1 +#define FU_ERROR_INVALID_ARGUMENTS 0 +#define FU_ERROR_NO_SUCH_CMD 1 + +typedef struct { + GOptionContext *context; + GPtrArray *cmd_array; +} FuUtilPrivate; + +typedef gboolean (*FuUtilPrivateCb) (FuUtilPrivate *util, + gchar **values, + GError **error); + +typedef struct { + gchar *name; + gchar *arguments; + gchar *description; + FuUtilPrivateCb callback; +} FuUtilItem; + +/** + * fu_util_item_free: + **/ +static void +fu_util_item_free (FuUtilItem *item) +{ + g_free (item->name); + g_free (item->arguments); + g_free (item->description); + g_free (item); +} + +/* + * fu_sort_command_name_cb: + */ +static gint +fu_sort_command_name_cb (FuUtilItem **item1, FuUtilItem **item2) +{ + return g_strcmp0 ((*item1)->name, (*item2)->name); +} + +/** + * fu_util_add: + **/ +static void +fu_util_add (GPtrArray *array, + const gchar *name, + const gchar *arguments, + const gchar *description, + FuUtilPrivateCb callback) +{ + guint i; + FuUtilItem *item; + _cleanup_strv_free_ gchar **names = NULL; + + g_return_if_fail (name != NULL); + g_return_if_fail (description != NULL); + g_return_if_fail (callback != NULL); + + /* add each one */ + names = g_strsplit (name, ",", -1); + for (i = 0; names[i] != NULL; i++) { + item = g_new0 (FuUtilItem, 1); + item->name = g_strdup (names[i]); + if (i == 0) { + item->description = g_strdup (description); + } else { + /* TRANSLATORS: this is a command alias */ + item->description = g_strdup_printf (_("Alias to %s"), + names[0]); + } + item->arguments = g_strdup (arguments); + item->callback = callback; + g_ptr_array_add (array, item); + } +} + +/** + * fu_util_get_descriptions: + **/ +static gchar * +fu_util_get_descriptions (GPtrArray *array) +{ + guint i; + guint j; + guint len; + const guint max_len = 35; + FuUtilItem *item; + GString *string; + + /* print each command */ + string = g_string_new (""); + for (i = 0; i < array->len; i++) { + item = g_ptr_array_index (array, i); + g_string_append (string, " "); + g_string_append (string, item->name); + len = strlen (item->name) + 2; + if (item->arguments != NULL) { + g_string_append (string, " "); + g_string_append (string, item->arguments); + len += strlen (item->arguments) + 1; + } + if (len < max_len) { + for (j = len; j < max_len + 1; j++) + g_string_append_c (string, ' '); + g_string_append (string, item->description); + g_string_append_c (string, '\n'); + } else { + g_string_append_c (string, '\n'); + for (j = 0; j < max_len + 1; j++) + g_string_append_c (string, ' '); + g_string_append (string, item->description); + g_string_append_c (string, '\n'); + } + } + + /* remove trailing newline */ + if (string->len > 0) + g_string_set_size (string, string->len - 1); + + return g_string_free (string, FALSE); +} + +/** + * fu_util_run: + **/ +static gboolean +fu_util_run (FuUtilPrivate *priv, const gchar *command, gchar **values, GError **error) +{ + guint i; + FuUtilItem *item; + _cleanup_string_free_ GString *string = NULL; + + /* find command */ + for (i = 0; i < priv->cmd_array->len; i++) { + item = g_ptr_array_index (priv->cmd_array, i); + if (g_strcmp0 (item->name, command) == 0) + return item->callback (priv, values, error); + } + + /* not found */ + string = g_string_new (""); + /* TRANSLATORS: error message */ + g_string_append_printf (string, "%s\n", + _("Command not found, valid commands are:")); + for (i = 0; i < priv->cmd_array->len; i++) { + item = g_ptr_array_index (priv->cmd_array, i); + g_string_append_printf (string, " * %s %s\n", + item->name, + item->arguments ? item->arguments : ""); + } + g_set_error_literal (error, FU_ERROR, FU_ERROR_NO_SUCH_CMD, string->str); + return FALSE; +} + +/** + * fu_util_get_devices: + **/ +static gboolean +fu_util_get_devices (FuUtilPrivate *priv, gchar **values, GError **error) +{ + _cleanup_object_unref_ GDBusConnection *conn = NULL; + _cleanup_object_unref_ GDBusProxy *proxy = NULL; + _cleanup_variant_unref_ GVariant *val = NULL; + const gchar **guids = NULL; + guint i; + + conn = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error); + if (conn == NULL) + return FALSE; + proxy = g_dbus_proxy_new_sync (conn, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + FWUPD_DBUS_SERVICE, + FWUPD_DBUS_PATH, + FWUPD_DBUS_INTERFACE, + NULL, + error); + if (proxy == NULL) + return FALSE; + val = g_dbus_proxy_call_sync (proxy, + "GetDevices", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + error); + if (val == NULL) + return FALSE; + g_variant_get (val, "(^a&s)", &guids); + g_assert (guids != NULL); + if (guids[0] == NULL) + g_print ("No hardware detected with firmware update capaility\n"); + for (i = 0; guids[i] != NULL; i++) + g_print ("%i: %s\n", i, guids[i]); + return TRUE; +} + +/** + * fu_util_update_offline: + **/ +static gboolean +fu_util_update_offline (FuUtilPrivate *priv, gchar **values, GError **error) +{ + //FIXME + return TRUE; +} + +/** + * fu_util_ignore_cb: + **/ +static void +fu_util_ignore_cb (const gchar *log_domain, GLogLevelFlags log_level, + const gchar *message, gpointer user_data) +{ +} + +/** + * main: + **/ +int +main (int argc, char *argv[]) +{ + FuUtilPrivate *priv; + gboolean ret; + gboolean verbose = FALSE; + guint retval = 1; + _cleanup_error_free_ GError *error = NULL; + _cleanup_free_ gchar *cmd_descriptions = NULL; + const GOptionEntry options[] = { + { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, + /* TRANSLATORS: command line option */ + _("Show extra debugging information"), NULL }, + { NULL} + }; + + setlocale (LC_ALL, ""); + + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); + + /* create helper object */ + priv = g_new0 (FuUtilPrivate, 1); + + /* add commands */ + priv->cmd_array = g_ptr_array_new_with_free_func ((GDestroyNotify) fu_util_item_free); + fu_util_add (priv->cmd_array, + "get-devices", + NULL, + /* TRANSLATORS: command description */ + _("Get all devices that support firmware updates"), + fu_util_get_devices); + fu_util_add (priv->cmd_array, + "update-offline", + NULL, + /* TRANSLATORS: command description */ + _("Install the update the next time the computer is rebooted"), + fu_util_update_offline); + + /* sort by command name */ + g_ptr_array_sort (priv->cmd_array, + (GCompareFunc) fu_sort_command_name_cb); + + /* get a list of the commands */ + priv->context = g_option_context_new (NULL); + cmd_descriptions = fu_util_get_descriptions (priv->cmd_array); + g_option_context_set_summary (priv->context, cmd_descriptions); + + /* TRANSLATORS: program name */ + g_set_application_name (_("Firmware Update")); + g_option_context_add_main_entries (priv->context, options, NULL); + ret = g_option_context_parse (priv->context, &argc, &argv, &error); + if (!ret) { + /* TRANSLATORS: the user didn't read the man page */ + g_print ("%s: %s\n", _("Failed to parse arguments"), + error->message); + goto out; + } + + /* set verbose? */ + if (verbose) { + g_setenv ("FWUPD_VERBOSE", "1", FALSE); + } else { + g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, + fu_util_ignore_cb, NULL); + } + + /* run the specified command */ + ret = fu_util_run (priv, argv[1], (gchar**) &argv[2], &error); + if (!ret) { + if (g_error_matches (error, FU_ERROR, FU_ERROR_NO_SUCH_CMD)) { + _cleanup_free_ gchar *tmp = NULL; + tmp = g_option_context_get_help (priv->context, TRUE, NULL); + g_print ("%s", tmp); + } else { + g_print ("%s\n", error->message); + } + goto out; + } + + /* success */ + retval = 0; +out: + if (priv != NULL) { + if (priv->cmd_array != NULL) + g_ptr_array_unref (priv->cmd_array); + g_option_context_free (priv->context); + g_free (priv); + } + return retval; +} + diff --git a/src/fwupd.gresource.xml b/src/fwupd.gresource.xml new file mode 100644 index 000000000..ea5d606d3 --- /dev/null +++ b/src/fwupd.gresource.xml @@ -0,0 +1,6 @@ + + + + org.freedesktop.fwupd.xml + + diff --git a/src/org.freedesktop.fwupd.xml b/src/org.freedesktop.fwupd.xml new file mode 100644 index 000000000..20c45fa24 --- /dev/null +++ b/src/org.freedesktop.fwupd.xml @@ -0,0 +1,84 @@ + + + + + + + The interface used for quering firmware for the system. + + + + + + + + + + The daemon version. + + + + + + + + + + + Gets a list of all the devices that support UEFI firmware upgrading. + + + + + + + An array of GUIDs. + + + + + + + + + + + Schedules an update to be done offline. + + + + + + + A GUID of the hardware to update. + + + + + + + + An index into the array of file descriptors that may have + been sent with the DBus message. + + + + + + + + + + + + Some value on the interface or the number of devices or + profiles has changed. + + + + + + +