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. + + + + + + +