--- /dev/null
+*.cache
+*.swp
+
+/build-aux
+/m4
+/build_*
+
+aclocal.m4
+config.h
+config.h.in
+config.log
+config.status
+configure
+debugfiles.list
+debuglinks.list
+debugsources.list
+documentation.list
+initrd-recovery.manifest
+Makefile.in
--- /dev/null
+Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
--- /dev/null
+ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
+
+SUBDIRS = .
+
+initrd_recovery_libexecdir=$(INITRD_RECOVERY_LIBEXEC_DIR)
+initrd_recovery_datadir=$(INITRD_RECOVERY_DATA_DIR)
+initrd_recovery_install_dropindir=$(INITRD_RECOVERY_INSTALL_DROPIN_DIR)
+
+DEFAULT_CFLAGS = \
+ $(LIBSYSTEM_CFLAGS) \
+ $(OUR_CFLAGS)
+
+DEFAULT_LDFLAGS = \
+ $(LIBSYSTEM_LDFLAGS) \
+ $(OUR_LDFLAGS)
+
+DEFAULT_LIBS = \
+ $(LIBSYSTEM_LIBS) \
+ libinitrd-recovery-shared.la
+
+AM_CPPFLAGS = \
+ -include $(top_builddir)/config.h \
+ -I $(top_srcdir)/src \
+ -I $(top_srcdir)/src/shared \
+ $(DEFAULT_CFLAGS)
+
+AM_CFLAGS = $(DEFAULT_CFLAGS)
+AM_LDFLAGS = $(DEFAULT_LDFLAGS)
+AM_LIBS = $(DEFAULT_LIBS)
+
+CLEANFILES =
+EXTRA_DIST =
+
+lib_LTLIBRARIES =
+noinst_LTLIBRARIES =
+
+bin_PROGRAMS =
+
+initrd_recovery_install_dropin_DATA =
+
+# ------------------------------------------------------------------------------
+noinst_LTLIBRARIES += \
+ libinitrd-recovery-shared.la
+
+libinitrd_recovery_shared_la_SOURCES = \
+ src/shared/log.c \
+ src/shared/log.h
+
+libinitrd_recovery_shared_la_CFLAGS = \
+ $(AM_CFLAGS)
+
+libinitrd_recovery_shared_la_LIBADD = \
+ $(LIBSYSTEM_LIBS)
+
+# ------------------------------------------------------------------------------
+if RECOVERY_GUI
+noinst_LTLIBRARIES += \
+ librui.la
+
+librui_la_SOURCES = \
+ src/librui/graphics.c \
+ src/librui/input-events.c \
+ src/librui/resources.c \
+ src/librui/rui-description.c \
+ src/librui/rui-images.c \
+ src/librui/rui-menu.c \
+ src/librui/rui-progress-bar.c \
+ src/librui/rui-rulers.c \
+ src/librui/rui.c
+
+if HAVE_TDM
+librui_la_SOURCES += \
+ src/librui/graphics-tdm.c \
+ src/librui/tdm-if.c
+else
+librui_la_SOURCES += \
+ src/librui/graphics-fbdev-common.c \
+ src/librui/graphics-fbdev.c
+endif
+
+librui_la_CFLAGS = \
+ $(LIBPNG_CFLAGS) \
+ $(LIBTDM_CFLAGS) \
+ $(VCONF_INTERNAL_KEYS) \
+ $(AM_CFLAGS) \
+ -I $(top_srcdir)/src/librui \
+ -I $(top_srcdir)/src/fonts
+
+librui_la_LIBADD = \
+ $(LIBPNG_LIBS) \
+ $(LIBTDM_LIBS) \
+ $(AM_LIBS)
+endif
+
+# ------------------------------------------------------------------------------
+system_recovery_datadir = $(SYSTEM_RECOVERY_DATA_DIR)
+system_recovery_imagedir = $(SYSTEM_RECOVERY_IMAGE_DIR)
+system_recovery_libexecdir = $(SYSTEM_RECOVERY_LIBEXEC_DIR)
+
+system_recovery_SOURCES = \
+ src/system-recovery/recovery-main.c
+
+system_recovery_CFLAGS = \
+ $(AM_CFLAGS) \
+ -DSYSTEM_RECOVERY_CONFIG_FILE=\""${system_recovery_datadir}/system-recovery.cfg"\" \
+ $(LIBCONFIG_CFLAGS) \
+ -I $(top_srcdir)/src/system-recovery
+
+system_recovery_LDADD = \
+ $(AM_LIBS) \
+ $(LIBCONFIG_LIBS)
+
+if RECOVERY_GUI
+system_recovery_SOURCES += \
+ src/system-recovery/process-util.c \
+ src/system-recovery/recovery-rui.c
+
+system_recovery_CFLAGS += \
+ -I $(librui_la_CFLAGS) \
+ -I $(top_srcdir)/src/librui
+
+system_recovery_LDADD += \
+ librui.la
+
+system_recovery_image_DATA = \
+ src/system-recovery/res/images/font.png \
+ src/system-recovery/res/images/menu-title.png \
+ src/system-recovery/res/images/tizen-anim.png \
+ src/system-recovery/res/images/warning.png
+
+initrd_recovery_install_dropin_DATA += \
+ src/system-recovery/50-system-recovery-sprd.list
+
+else
+
+system_recovery_SOURCES += \
+ src/system-recovery/recovery-headless.c
+endif
+
+system_recovery_libexec_PROGRAMS = \
+ system-recovery
+
+system_recovery_data_DATA = \
+ src/system-recovery/system-recovery.cfg
+
+system_recovery_libexec_SCRIPTS = \
+ src/system-recovery/recovery-init
+
+sbin_SCRIPTS = \
+ src/system-recovery/recovery-action-set
+
+initrd_recovery_install_dropin_DATA += \
+ src/system-recovery/50-system-recovery.list
+
+EXTRA_DIST += \
+ src/system-recovery/50-system-recovery.list.m4 \
+ src/system-recovery/recovery-init.in \
+ src/system-recovery/recovery-action-set.in \
+ src/system-recovery/system-recovery.cfg.m4.in
+
+CLEANFILES += \
+ src/system-recovery/50-system-recovery.list \
+ src/system-recovery/recovery-init \
+ src/system-recovery/system-recovery.cfg.m4 \
+ src/system-recovery/recovery-action-set
+
+# ------------------------------------------------------------------------------
+substitutions = \
+ '|PACKAGE_VERSION=$(PACKAGE_VERSION)|' \
+ '|PACKAGE_NAME=$(PACKAGE_NAME)|' \
+ '|PACKAGE_URL=$(PACKAGE_URL)|' \
+ '|includedir=$(includedir)|' \
+ '|VERSION=$(VERSION)|' \
+ '|MKDIR_P=$(MKDIR_P)|' \
+ '|INITRD_RECOVERY_INSTALL_DROPIN_DIR=$(INITRD_RECOVERY_INSTALL_DROPIN_DIR)|' \
+ '|INITRD_RECOVERY_LIBEXEC_DIR=$(INITRD_RECOVERY_LIBEXEC_DIR)|' \
+ '|SYSTEM_RECOVERY_IMAGE_DIR=$(SYSTEM_RECOVERY_IMAGE_DIR)|' \
+ '|SYSTEM_RECOVERY_LIBEXEC_DIR=$(SYSTEM_RECOVERY_LIBEXEC_DIR)|' \
+ '|SYSTEM_RECOVERY_DATA_DIR=$(SYSTEM_RECOVERY_DATA_DIR)|' \
+ '|SYSTEM_RECOVERY_ACTION_FILE=$(SYSTEM_RECOVERY_ACTION_FILE)|' \
+ '|RECOVERY_GUI=$(RECOVERY_GUI)|'
+
+SED_PROCESS = \
+ $(AM_V_GEN)$(MKDIR_P) $(dir $@) && \
+ $(SED) $(subst '|,-e 's|@,$(subst =,\@|,$(subst |',|g',$(substitutions)))) \
+ < $< > $@
+
+src/%: src/%.in Makefile
+ $(SED_PROCESS)
+
+src/%: src/%.m4
+ $(AM_V_at)$(MKDIR_P) $(dir $@)
+ $(AM_V_M4)$(M4) -P $(M4_DEFINES) < $< > $@
+
+install-exec-hook: $(INSTALL_EXEC_HOOKS)
--- /dev/null
+#!/bin/sh
+
+set -e
+
+if [ -f .git/hooks/pre-commit.sample ] && [ ! -f .git/hooks/pre-commit ]; then
+ # This part is allowed to fail
+ cp -p .git/hooks/pre-commit.sample .git/hooks/pre-commit && \
+ chmod +x .git/hooks/pre-commit && \
+ echo "Activated pre-commit hook." || :
+fi
+
+# README and INSTALL are required by automake, but may be deleted by
+# clean up rules. to get automake to work, simply touch these here,
+# they will be regenerated from their corresponding *.in files by
+# ./configure anyway.
+touch README INSTALL
+
+# Make sure m4 directory exist
+mkdir -p m4
+
+autoreconf --force --install --verbose || exit $?
--- /dev/null
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ([2.69])
+AC_INIT([initrd-recovery], [2.1.1], [walyong.cho@samsung.com])
+
+AC_CONFIG_MACRO_DIR([m4])
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_AUX_DIR([build-aux])
+
+AC_USE_SYSTEM_EXTENSIONS
+AC_SYS_LARGEFILE
+AC_PREFIX_DEFAULT([/usr])
+AM_INIT_AUTOMAKE([foreign subdir-objects])
+
+LT_PREREQ(2.2)
+LT_INIT([disable-static])
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+AC_PROG_MKDIR_P
+AC_PATH_PROG([M4], [m4])
+
+# Checks for libraries.
+
+# Checks for header files.
+AC_CHECK_HEADERS([fcntl.h limits.h mntent.h stdint.h stdlib.h string.h sys/ioctl.h sys/mount.h unistd.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_CHECK_HEADER_STDBOOL
+AC_C_INLINE
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_TYPE_UINT32_T
+
+# Checks for library functions.
+AC_FUNC_FORK
+AC_FUNC_GETMNTENT
+AC_FUNC_MALLOC
+AC_FUNC_MMAP
+AC_CHECK_FUNCS([dup2 getmntent memset munmap strcasecmp strchr strdup strerror strrchr strstr])
+
+# ------------------------------------------------------------------------------
+our_cflags=" \
+ -g -O2 \
+ -Werror \
+ -fpie"
+
+our_ldflags=" \
+ -Wl,--as-needed \
+ -Wl,--no-undefined \
+ -Wl,--gc-sections \
+ -Wl,-z,relro \
+ -Wl,-z,now \
+ -pie"
+
+AC_SUBST([OUR_CFLAGS], "$our_cflags")
+AC_SUBST([OUR_LDFLAGS], "$our_ldflags")
+
+M4_DEFINES=
+# ------------------------------------------------------------------------------
+AC_ARG_WITH([tdm],
+ AS_HELP_STRING([--without-tdm], [disable TDM/TBM graphical backend (default: test)]))
+PKG_CHECK_MODULES([LIBCONFIG],
+ [libconfig >= 1.6],
+ have_libconfig=yes,
+ have_libconfig=no)
+
+if test "x$have_libconfig" = "xno"; then
+ AC_MSG_ERROR([libconfig not found])
+fi
+
+AC_ARG_ENABLE([recovery-gui],
+ AS_HELP_STRING([--disable-recovery-gui], [disable recovery gui mode]),
+ [case "${enableval}" in
+ yes) enable_recovery_gui=yes ;;
+ no) enable_recovery_gui=no ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --disable-recovery-gui) ;;
+ esac],
+ enable_recovery_gui=yes)
+
+have_libtdm=no
+if test "x$enable_recovery_gui" == "xyes"; then
+ M4_DEFINES="$M4_DEFINES -DRECOVERY_GUI"
+ AC_SUBST([OUR_CFLAGS], "$OUR_CFLAGS -DRECOVERY_GUI")
+ PKG_CHECK_MODULES(LIBPNG, [libpng])
+ if test "x$with_tdm" != "xno"; then
+ PKG_CHECK_MODULES(LIBTDM,
+ [libtdm >= 1.7.0],
+ [AC_DEFINE(HAVE_TDM, 1, [Define if using TDM/TBM graphical backend])
+ have_libtdm=yes])
+ if test "x$with_tdm" = "xyes" -a "x$have_libtdm" = "xno"; then
+ AC_MSG_ERROR([--with-tdm has been specified but libtdm is not available.])
+ fi
+ fi
+ RECOVERY_GUI="GUI"
+else
+ RECOVERY_GUI="NO"
+fi
+
+AC_SUBST([RECOVERY_GUI])
+AM_CONDITIONAL([RECOVERY_GUI], [test "x$enable_recovery_gui" != "xno"])
+AM_CONDITIONAL([HAVE_TDM], [test "x$have_libtdm" = "xyes"])
+
+SYSTEM_RECOVERY_DATA_DIR="${datadir}/system-recovery"
+AC_DEFINE_UNQUOTED([SYSTEM_RECOVERY_DATA_DIR], ["$SYSTEM_RECOVERY_DATA_DIR"], "Directory where data for system-recovery UI are stored")
+AC_SUBST([SYSTEM_RECOVERY_DATA_DIR])
+
+SYSTEM_RECOVERY_IMAGE_DIR="${datadir}/system-recovery/res/images"
+AC_DEFINE_UNQUOTED([SYSTEM_RECOVERY_IMAGE_DIR], ["$SYSTEM_RECOVERY_IMAGE_DIR"], "Directory where images for system-recovery UI are stored")
+AC_SUBST([SYSTEM_RECOVERY_IMAGE_DIR])
+
+RUI_IMAGES_DIR="${SYSTEM_RECOVERY_IMAGE_DIR}"
+AC_DEFINE_UNQUOTED([RUI_IMAGES_DIR], ["$RUI_IMAGES_DIR"], "Directory where images for system-recovery UI are stored")
+
+SYSTEM_RECOVERY_LIBEXEC_DIR="${libexecdir}/system-recovery"
+AC_DEFINE_UNQUOTED([SYSTEM_RECOVERY_LIBEXEC_DIR], ["$SYSTEM_RECOVERY_LIBEXEC_DIR"], "Directory where sub-programmes for system-recovery UI are stored")
+AC_SUBST([SYSTEM_RECOVERY_LIBEXEC_DIR])
+
+SYSTEM_RECOVERY_ACTION_FILE="/opt/.recovery.action"
+AC_DEFINE_UNQUOTED([SYSTEM_RECOVERY_ACTION_FILE], ["$SYSTEM_RECOVERY_ACTION_FILE"], "File where recovery action is stored")
+AC_SUBST([SYSTEM_RECOVERY_ACTION_FILE])
+
+INITRD_RECOVERY_DATA_DIR="${datadir}/initrd-recovery"
+AC_DEFINE_UNQUOTED([INITRD_RECOVERY_DATA_DIR], ["$INITRD_RECOVERY_DATA_DIR"], "Directory where data for recovery initrd are stored")
+AC_SUBST([INITRD_RECOVERY_DATA_DIR])
+
+INITRD_RECOVERY_INSTALL_DROPIN_DIR="${INITRD_RECOVERY_DATA_DIR}/initrd.list.d"
+AC_DEFINE_UNQUOTED([INITRD_RECOVERY_INSTALL_DROPIN_DIR], ["$INITRD_RECOVERY_INSTALL_DROPIN_DIR"], "Directory where configuration drop-in files for recovery initrd are stored")
+AC_SUBST([INITRD_RECOVERY_INSTALL_DROPIN_DIR])
+
+INITRD_RECOVERY_LIBEXEC_DIR="${libexecdir}/initrd-recovery"
+AC_DEFINE_UNQUOTED([INITRD_RECOVERY_LIBEXEC_DIR], ["$INITRD_RECOVERY_LIBEXEC_DIR"], "Directory where sub-progremmes for recovery initrd are stored")
+AC_SUBST([INITRD_RECOVERY_LIBEXEC_DIR])
+
+# ------------------------------------------------------------------------------
+AC_SUBST(M4_DEFINES)
+
+# ------------------------------------------------------------------------------
+AC_CONFIG_FILES([Makefile])
+
+AC_OUTPUT
+AC_MSG_RESULT([
+ $PACKAGE_NAME $VERSION
+ =====================
+ prefix: ${prefix}
+ recovery gui mode: ${enable_recovery_gui}
+ with TDM: ${have_libtdm}
+ OUR CFLAGS: ${OUR_CFLAGS} ${CFLAGS}
+])
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_"/>
+ </request>
+</manifest>
--- /dev/null
+Name: system-recovery
+Summary: System recovery
+Version: 0.2.0
+Release: 0
+Group: System/Utilities
+License: Apache-2.0
+ExclusiveArch: %{arm}
+
+Source0: %{name}-%{version}.tar.gz
+Source1001: system-recovery.manifest
+
+BuildRequires: autoconf
+BuildRequires: automake
+BuildRequires: libtool
+BuildRequires: pkgconfig(libconfig)
+BuildRequires: pkgconfig(libtdm)
+BuildRequires: pkgconfig(libpng)
+
+Requires: initrd-recovery
+Requires: system-recovery-compat = %{version}-%{release}
+Recommends: system-recovery-non_gui = %{version}-%{release}
+
+%description
+A simple initrd menu for system recovery.
+
+# non_gui profile: common, wearable
+%package non_gui
+Summary: system-recovery without gui
+Provides: system-recovery-compat = %{version}-%{release}
+Conflicts: system-recovery-gui
+%description non_gui
+system-recovery package without gui
+
+# gui profile: mobile
+%package gui
+Summary: system-recovery with gui
+Provides: system-recovery-compat = %{version}-%{release}
+Conflicts: system-recovery-non_gui
+%description gui
+system-recovery package with gui
+
+# Configuration for mkinitrd-recovery, one package per target
+%package sprd
+Summary: mkinitrd-recovery configuration file for spreadtrum platform
+Group: System/Utilities
+License: Apache-2.0
+Requires: system-recovery-gui
+%description sprd
+mkinitrd-recovery configuration file for spreadtrum platform
+
+%prep
+%setup -q
+
+%build
+cp %{SOURCE1001} .
+%autogen
+
+# common, wearalbe: without gui
+mkdir -p build_non_gui
+ln -nfs ../%{_configure} build_non_gui
+pushd build_non_gui
+%configure \
+ --disable-recovery-gui \
+ --srcdir=../
+make %{?_smp_mflags}
+popd
+
+# mobile: with gui
+mkdir -p build_gui
+ln -nfs ../%{_configure} build_gui
+pushd build_gui
+%configure \
+ --srcdir=../
+make %{?_smp_mflags}
+popd
+
+%install
+# common, wearable
+pushd build_non_gui
+%make_install
+mv %{buildroot}%{_libexecdir}/system-recovery/system-recovery \
+ %{buildroot}%{_libexecdir}/system-recovery/system-recovery.non_gui \
+
+mv %{buildroot}%{_datadir}/initrd-recovery/initrd.list.d/50-system-recovery.list \
+ %{buildroot}%{_datadir}/initrd-recovery/initrd.list.d/50-system-recovery-non_gui.list
+popd
+
+# mobile
+pushd build_gui
+%make_install
+mv %{buildroot}%{_libexecdir}/system-recovery/system-recovery \
+ %{buildroot}%{_libexecdir}/system-recovery/system-recovery.gui \
+
+mv %{buildroot}%{_datadir}/initrd-recovery/initrd.list.d/50-system-recovery.list \
+ %{buildroot}%{_datadir}/initrd-recovery/initrd.list.d/50-system-recovery-gui.list
+popd
+
+%files
+%defattr(-,root,root,-)
+%manifest system-recovery.manifest
+%license LICENSE
+%{_datadir}/system-recovery/system-recovery.cfg
+%{_libexecdir}/system-recovery/recovery-init
+%{_sbindir}/recovery-action-set
+
+%files non_gui
+%{_datadir}/initrd-recovery/initrd.list.d/50-system-recovery-non_gui.list
+%{_libexecdir}/system-recovery/system-recovery.non_gui
+
+%files gui
+%{_datadir}/initrd-recovery/initrd.list.d/50-system-recovery-gui.list
+%{_datadir}/system-recovery/res/images/*.png
+%{_libexecdir}/system-recovery/system-recovery.gui
+
+%files sprd
+%{_datadir}/initrd-recovery/initrd.list.d/50-system-recovery-sprd.list
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+struct {
+ unsigned width;
+ unsigned height;
+ unsigned cwidth;
+ unsigned cheight;
+ unsigned char rundata[2973];
+} font = {
+ .width = 960,
+ .height = 18,
+ .cwidth = 10,
+ .cheight = 18,
+ .rundata = {
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x55, 0x82, 0x06, 0x82, 0x02, 0x82, 0x10, 0x82,
+ 0x11, 0x83, 0x08, 0x82, 0x0a, 0x82, 0x04, 0x82, 0x46, 0x82, 0x08, 0x82, 0x07, 0x84, 0x06,
+ 0x84, 0x0a, 0x81, 0x03, 0x88, 0x04, 0x84, 0x04, 0x88, 0x04, 0x84, 0x06, 0x84, 0x1e, 0x81,
+ 0x0e, 0x81, 0x0a, 0x84, 0x06, 0x84, 0x07, 0x82, 0x05, 0x85, 0x07, 0x84, 0x04, 0x86, 0x04,
+ 0x88, 0x02, 0x88, 0x04, 0x84, 0x04, 0x82, 0x04, 0x82, 0x02, 0x88, 0x05, 0x86, 0x01, 0x82,
+ 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x04, 0x84, 0x04,
+ 0x86, 0x06, 0x84, 0x04, 0x86, 0x06, 0x84, 0x04, 0x88, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82,
+ 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02,
+ 0x88, 0x03, 0x86, 0x0e, 0x86, 0x06, 0x82, 0x11, 0x82, 0x10, 0x82, 0x18, 0x82, 0x0f, 0x84,
+ 0x0d, 0x82, 0x1c, 0x82, 0x09, 0x84, 0x7f, 0x16, 0x84, 0x05, 0x82, 0x05, 0x84, 0x07, 0x83,
+ 0x02, 0x82, 0x19, 0x82, 0x06, 0x82, 0x02, 0x82, 0x06, 0x82, 0x01, 0x82, 0x03, 0x86, 0x04,
+ 0x83, 0x02, 0x82, 0x03, 0x82, 0x01, 0x82, 0x07, 0x82, 0x09, 0x82, 0x06, 0x82, 0x3e, 0x82,
+ 0x04, 0x84, 0x06, 0x83, 0x06, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x03,
+ 0x82, 0x09, 0x82, 0x02, 0x82, 0x09, 0x82, 0x03, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82,
+ 0x1c, 0x82, 0x0e, 0x82, 0x08, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x05, 0x84, 0x04,
+ 0x82, 0x02, 0x82, 0x05, 0x82, 0x02, 0x82, 0x03, 0x82, 0x03, 0x82, 0x03, 0x82, 0x08, 0x82,
+ 0x09, 0x82, 0x02, 0x82, 0x03, 0x82, 0x04, 0x82, 0x05, 0x82, 0x0a, 0x82, 0x03, 0x82, 0x04,
+ 0x82, 0x02, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x83, 0x03, 0x82, 0x03, 0x82, 0x02, 0x82,
+ 0x03, 0x82, 0x03, 0x82, 0x04, 0x82, 0x02, 0x82, 0x03, 0x82, 0x03, 0x82, 0x04, 0x82, 0x02,
+ 0x82, 0x06, 0x82, 0x05, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82,
+ 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x08, 0x82, 0x03, 0x82, 0x08, 0x82, 0x0c,
+ 0x82, 0x05, 0x84, 0x11, 0x82, 0x0f, 0x82, 0x18, 0x82, 0x0e, 0x82, 0x02, 0x82, 0x0c, 0x82,
+ 0x1c, 0x82, 0x0b, 0x82, 0x7f, 0x15, 0x82, 0x08, 0x82, 0x08, 0x82, 0x05, 0x82, 0x01, 0x82,
+ 0x01, 0x82, 0x19, 0x82, 0x06, 0x82, 0x02, 0x82, 0x06, 0x82, 0x01, 0x82, 0x02, 0x82, 0x01,
+ 0x82, 0x01, 0x82, 0x02, 0x82, 0x01, 0x82, 0x01, 0x82, 0x03, 0x82, 0x01, 0x82, 0x07, 0x82,
+ 0x08, 0x82, 0x08, 0x82, 0x3d, 0x82, 0x03, 0x82, 0x02, 0x82, 0x04, 0x84, 0x05, 0x82, 0x04,
+ 0x82, 0x02, 0x82, 0x04, 0x82, 0x06, 0x83, 0x03, 0x82, 0x08, 0x82, 0x04, 0x81, 0x09, 0x82,
+ 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x1a, 0x82, 0x10, 0x82, 0x06, 0x82, 0x04,
+ 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82, 0x02, 0x82, 0x03, 0x82, 0x03, 0x82, 0x03, 0x82,
+ 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02,
+ 0x82, 0x04, 0x82, 0x05, 0x82, 0x0a, 0x82, 0x03, 0x82, 0x03, 0x82, 0x03, 0x82, 0x08, 0x83,
+ 0x02, 0x83, 0x02, 0x83, 0x03, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02,
+ 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x05, 0x82, 0x05, 0x82,
+ 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82, 0x02, 0x82, 0x04,
+ 0x82, 0x02, 0x82, 0x09, 0x82, 0x03, 0x82, 0x08, 0x82, 0x0c, 0x82, 0x04, 0x82, 0x02, 0x82,
+ 0x11, 0x82, 0x0e, 0x82, 0x18, 0x82, 0x0e, 0x82, 0x02, 0x82, 0x0c, 0x82, 0x0b, 0x82, 0x0b,
+ 0x82, 0x02, 0x82, 0x0b, 0x82, 0x4d, 0x82, 0x45, 0x82, 0x08, 0x82, 0x08, 0x82, 0x05, 0x82,
+ 0x02, 0x83, 0x1a, 0x82, 0x07, 0x81, 0x02, 0x81, 0x07, 0x82, 0x01, 0x82, 0x02, 0x82, 0x01,
+ 0x82, 0x05, 0x82, 0x01, 0x84, 0x04, 0x82, 0x01, 0x82, 0x07, 0x82, 0x08, 0x82, 0x08, 0x82,
+ 0x06, 0x82, 0x02, 0x82, 0x06, 0x82, 0x28, 0x82, 0x04, 0x82, 0x02, 0x82, 0x03, 0x82, 0x01,
+ 0x82, 0x05, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x05, 0x84, 0x03, 0x82, 0x08, 0x82,
+ 0x0d, 0x82, 0x03, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x19, 0x82, 0x12, 0x82, 0x05,
+ 0x82, 0x04, 0x82, 0x02, 0x82, 0x02, 0x84, 0x03, 0x82, 0x02, 0x82, 0x03, 0x82, 0x03, 0x82,
+ 0x03, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x08, 0x82, 0x08, 0x82, 0x04,
+ 0x82, 0x05, 0x82, 0x0a, 0x82, 0x03, 0x82, 0x03, 0x82, 0x03, 0x82, 0x08, 0x83, 0x02, 0x83,
+ 0x02, 0x84, 0x02, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04,
+ 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x0b, 0x82, 0x05, 0x82, 0x04, 0x82, 0x02, 0x82,
+ 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08,
+ 0x82, 0x04, 0x82, 0x09, 0x82, 0x0b, 0x82, 0x03, 0x82, 0x04, 0x82, 0x20, 0x82, 0x18, 0x82,
+ 0x0e, 0x82, 0x10, 0x82, 0x0b, 0x82, 0x0b, 0x82, 0x02, 0x82, 0x0b, 0x82, 0x4d, 0x82, 0x45,
+ 0x82, 0x08, 0x82, 0x08, 0x82, 0x26, 0x82, 0x10, 0x88, 0x01, 0x82, 0x01, 0x82, 0x06, 0x83,
+ 0x01, 0x82, 0x04, 0x84, 0x08, 0x81, 0x08, 0x82, 0x0a, 0x82, 0x05, 0x82, 0x02, 0x82, 0x06,
+ 0x82, 0x28, 0x82, 0x03, 0x82, 0x04, 0x82, 0x05, 0x82, 0x0b, 0x82, 0x08, 0x82, 0x04, 0x82,
+ 0x01, 0x82, 0x03, 0x82, 0x08, 0x82, 0x0d, 0x82, 0x03, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04,
+ 0x82, 0x18, 0x82, 0x06, 0x88, 0x06, 0x82, 0x04, 0x82, 0x04, 0x82, 0x02, 0x82, 0x01, 0x85,
+ 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x03, 0x82, 0x03, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02,
+ 0x82, 0x08, 0x82, 0x08, 0x82, 0x08, 0x82, 0x04, 0x82, 0x05, 0x82, 0x0a, 0x82, 0x03, 0x82,
+ 0x02, 0x82, 0x04, 0x82, 0x08, 0x88, 0x02, 0x84, 0x02, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02,
+ 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x0b, 0x82,
+ 0x05, 0x82, 0x04, 0x82, 0x03, 0x82, 0x02, 0x82, 0x03, 0x82, 0x04, 0x82, 0x04, 0x84, 0x06,
+ 0x84, 0x08, 0x82, 0x05, 0x82, 0x09, 0x82, 0x0b, 0x82, 0x2b, 0x82, 0x18, 0x82, 0x0e, 0x82,
+ 0x10, 0x82, 0x1c, 0x82, 0x0b, 0x82, 0x4d, 0x82, 0x45, 0x82, 0x08, 0x82, 0x08, 0x82, 0x26,
+ 0x82, 0x11, 0x82, 0x01, 0x82, 0x03, 0x82, 0x01, 0x82, 0x09, 0x82, 0x06, 0x82, 0x12, 0x82,
+ 0x0a, 0x82, 0x06, 0x84, 0x07, 0x82, 0x27, 0x82, 0x04, 0x82, 0x04, 0x82, 0x05, 0x82, 0x0b,
+ 0x82, 0x07, 0x82, 0x04, 0x82, 0x02, 0x82, 0x03, 0x82, 0x01, 0x83, 0x04, 0x82, 0x01, 0x83,
+ 0x08, 0x82, 0x05, 0x82, 0x02, 0x82, 0x03, 0x82, 0x04, 0x82, 0x05, 0x83, 0x07, 0x83, 0x05,
+ 0x82, 0x16, 0x82, 0x08, 0x82, 0x03, 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x04, 0x82,
+ 0x02, 0x82, 0x02, 0x82, 0x04, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x08,
+ 0x82, 0x08, 0x82, 0x04, 0x82, 0x05, 0x82, 0x0a, 0x82, 0x03, 0x82, 0x02, 0x82, 0x04, 0x82,
+ 0x08, 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x04,
+ 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82,
+ 0x0a, 0x82, 0x05, 0x82, 0x04, 0x82, 0x03, 0x82, 0x02, 0x82, 0x03, 0x82, 0x01, 0x82, 0x01,
+ 0x82, 0x04, 0x84, 0x06, 0x84, 0x08, 0x82, 0x05, 0x82, 0x0a, 0x82, 0x0a, 0x82, 0x23, 0x85,
+ 0x03, 0x82, 0x01, 0x83, 0x06, 0x85, 0x05, 0x83, 0x01, 0x82, 0x04, 0x84, 0x04, 0x86, 0x05,
+ 0x85, 0x01, 0x81, 0x02, 0x82, 0x01, 0x83, 0x05, 0x84, 0x09, 0x84, 0x02, 0x82, 0x03, 0x82,
+ 0x06, 0x82, 0x05, 0x81, 0x01, 0x82, 0x01, 0x82, 0x03, 0x82, 0x01, 0x83, 0x06, 0x84, 0x04,
+ 0x82, 0x01, 0x83, 0x06, 0x83, 0x01, 0x82, 0x02, 0x82, 0x01, 0x84, 0x04, 0x86, 0x03, 0x86,
+ 0x04, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04,
+ 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x87, 0x05, 0x82, 0x08, 0x82, 0x08, 0x82, 0x26, 0x82,
+ 0x11, 0x82, 0x01, 0x82, 0x04, 0x86, 0x07, 0x82, 0x05, 0x83, 0x12, 0x82, 0x0a, 0x82, 0x04,
+ 0x88, 0x02, 0x88, 0x0c, 0x88, 0x10, 0x82, 0x04, 0x82, 0x04, 0x82, 0x05, 0x82, 0x0a, 0x82,
+ 0x06, 0x83, 0x04, 0x82, 0x03, 0x82, 0x03, 0x83, 0x02, 0x82, 0x03, 0x83, 0x02, 0x82, 0x07,
+ 0x82, 0x06, 0x84, 0x05, 0x82, 0x02, 0x83, 0x05, 0x83, 0x07, 0x83, 0x04, 0x82, 0x18, 0x82,
+ 0x06, 0x82, 0x04, 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x86, 0x04,
+ 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x86, 0x04, 0x86, 0x04, 0x82, 0x02, 0x84, 0x02, 0x88,
+ 0x05, 0x82, 0x0a, 0x82, 0x03, 0x85, 0x05, 0x82, 0x08, 0x82, 0x01, 0x82, 0x01, 0x82, 0x02,
+ 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x03, 0x82, 0x03, 0x82,
+ 0x04, 0x82, 0x02, 0x82, 0x03, 0x82, 0x05, 0x84, 0x07, 0x82, 0x05, 0x82, 0x04, 0x82, 0x03,
+ 0x82, 0x02, 0x82, 0x03, 0x82, 0x01, 0x82, 0x01, 0x82, 0x05, 0x82, 0x08, 0x82, 0x08, 0x82,
+ 0x06, 0x82, 0x0a, 0x82, 0x0a, 0x82, 0x22, 0x82, 0x03, 0x82, 0x02, 0x83, 0x02, 0x82, 0x04,
+ 0x82, 0x03, 0x82, 0x03, 0x82, 0x02, 0x83, 0x03, 0x82, 0x02, 0x82, 0x05, 0x82, 0x06, 0x82,
+ 0x03, 0x83, 0x02, 0x83, 0x02, 0x82, 0x06, 0x82, 0x0b, 0x82, 0x02, 0x82, 0x02, 0x82, 0x07,
+ 0x82, 0x05, 0x88, 0x02, 0x83, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x03, 0x83, 0x02, 0x82,
+ 0x04, 0x82, 0x02, 0x83, 0x03, 0x83, 0x02, 0x82, 0x02, 0x82, 0x04, 0x82, 0x04, 0x82, 0x06,
+ 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82, 0x02, 0x82,
+ 0x03, 0x82, 0x04, 0x82, 0x08, 0x82, 0x02, 0x84, 0x09, 0x82, 0x09, 0x84, 0x23, 0x82, 0x11,
+ 0x82, 0x01, 0x82, 0x06, 0x82, 0x01, 0x82, 0x05, 0x82, 0x05, 0x82, 0x01, 0x82, 0x11, 0x82,
+ 0x0a, 0x82, 0x06, 0x84, 0x07, 0x82, 0x26, 0x82, 0x05, 0x82, 0x04, 0x82, 0x05, 0x82, 0x08,
+ 0x83, 0x09, 0x82, 0x03, 0x82, 0x03, 0x82, 0x09, 0x82, 0x02, 0x82, 0x04, 0x82, 0x05, 0x82,
+ 0x06, 0x82, 0x02, 0x82, 0x05, 0x83, 0x01, 0x82, 0x17, 0x82, 0x16, 0x82, 0x06, 0x82, 0x05,
+ 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, 0x88, 0x02, 0x82, 0x03, 0x82, 0x03, 0x82, 0x08, 0x82,
+ 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x05,
+ 0x82, 0x0a, 0x82, 0x03, 0x82, 0x02, 0x82, 0x04, 0x82, 0x08, 0x82, 0x01, 0x82, 0x01, 0x82,
+ 0x02, 0x82, 0x02, 0x84, 0x02, 0x82, 0x04, 0x82, 0x02, 0x86, 0x04, 0x82, 0x04, 0x82, 0x02,
+ 0x86, 0x09, 0x82, 0x06, 0x82, 0x05, 0x82, 0x04, 0x82, 0x04, 0x84, 0x04, 0x82, 0x01, 0x82,
+ 0x01, 0x82, 0x04, 0x84, 0x07, 0x82, 0x07, 0x82, 0x07, 0x82, 0x0b, 0x82, 0x09, 0x82, 0x27,
+ 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82,
+ 0x04, 0x82, 0x06, 0x82, 0x03, 0x82, 0x03, 0x82, 0x04, 0x82, 0x05, 0x82, 0x0b, 0x82, 0x02,
+ 0x82, 0x01, 0x82, 0x08, 0x82, 0x05, 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x04, 0x82,
+ 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82, 0x07,
+ 0x82, 0x0a, 0x82, 0x06, 0x82, 0x04, 0x82, 0x03, 0x82, 0x02, 0x82, 0x03, 0x82, 0x04, 0x82,
+ 0x04, 0x84, 0x04, 0x82, 0x04, 0x82, 0x07, 0x82, 0x06, 0x82, 0x08, 0x82, 0x08, 0x82, 0x26,
+ 0x82, 0x0f, 0x88, 0x05, 0x82, 0x01, 0x82, 0x05, 0x82, 0x05, 0x82, 0x02, 0x82, 0x01, 0x82,
+ 0x0d, 0x82, 0x0a, 0x82, 0x05, 0x82, 0x02, 0x82, 0x06, 0x82, 0x26, 0x82, 0x05, 0x82, 0x04,
+ 0x82, 0x05, 0x82, 0x07, 0x82, 0x0c, 0x82, 0x02, 0x88, 0x08, 0x82, 0x02, 0x82, 0x04, 0x82,
+ 0x05, 0x82, 0x05, 0x82, 0x04, 0x82, 0x08, 0x82, 0x18, 0x82, 0x14, 0x82, 0x07, 0x82, 0x05,
+ 0x82, 0x01, 0x84, 0x03, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, 0x82,
+ 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x05,
+ 0x82, 0x0a, 0x82, 0x03, 0x82, 0x02, 0x82, 0x04, 0x82, 0x08, 0x82, 0x01, 0x82, 0x01, 0x82,
+ 0x02, 0x82, 0x02, 0x84, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02,
+ 0x82, 0x02, 0x82, 0x0a, 0x82, 0x05, 0x82, 0x05, 0x82, 0x04, 0x82, 0x04, 0x84, 0x04, 0x82,
+ 0x01, 0x82, 0x01, 0x82, 0x04, 0x84, 0x07, 0x82, 0x07, 0x82, 0x07, 0x82, 0x0b, 0x82, 0x09,
+ 0x82, 0x22, 0x87, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x88,
+ 0x04, 0x82, 0x06, 0x82, 0x03, 0x82, 0x03, 0x82, 0x04, 0x82, 0x05, 0x82, 0x0b, 0x82, 0x02,
+ 0x84, 0x09, 0x82, 0x05, 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82,
+ 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82, 0x08, 0x86, 0x05,
+ 0x82, 0x06, 0x82, 0x04, 0x82, 0x03, 0x82, 0x02, 0x82, 0x03, 0x82, 0x01, 0x82, 0x01, 0x82,
+ 0x05, 0x82, 0x05, 0x82, 0x04, 0x82, 0x06, 0x82, 0x07, 0x82, 0x08, 0x82, 0x08, 0x82, 0x26,
+ 0x82, 0x10, 0x82, 0x01, 0x82, 0x07, 0x82, 0x01, 0x82, 0x04, 0x82, 0x01, 0x83, 0x02, 0x82,
+ 0x03, 0x83, 0x0f, 0x82, 0x08, 0x82, 0x06, 0x82, 0x02, 0x82, 0x06, 0x82, 0x25, 0x82, 0x07,
+ 0x82, 0x02, 0x82, 0x06, 0x82, 0x06, 0x82, 0x07, 0x82, 0x04, 0x82, 0x07, 0x82, 0x09, 0x82,
+ 0x02, 0x82, 0x04, 0x82, 0x04, 0x82, 0x06, 0x82, 0x04, 0x82, 0x08, 0x82, 0x19, 0x82, 0x05,
+ 0x88, 0x05, 0x82, 0x08, 0x82, 0x05, 0x82, 0x02, 0x82, 0x04, 0x82, 0x04, 0x82, 0x02, 0x82,
+ 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x08, 0x82, 0x04,
+ 0x82, 0x02, 0x82, 0x04, 0x82, 0x05, 0x82, 0x05, 0x82, 0x03, 0x82, 0x03, 0x82, 0x03, 0x82,
+ 0x03, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x03, 0x83, 0x02, 0x82, 0x04, 0x82, 0x02,
+ 0x82, 0x08, 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x03, 0x82, 0x09, 0x82, 0x05, 0x82,
+ 0x05, 0x82, 0x04, 0x82, 0x04, 0x84, 0x04, 0x83, 0x02, 0x83, 0x03, 0x82, 0x02, 0x82, 0x06,
+ 0x82, 0x06, 0x82, 0x08, 0x82, 0x0c, 0x82, 0x08, 0x82, 0x21, 0x82, 0x04, 0x82, 0x02, 0x82,
+ 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x0a, 0x82, 0x06, 0x82, 0x03,
+ 0x82, 0x03, 0x82, 0x04, 0x82, 0x05, 0x82, 0x0b, 0x82, 0x02, 0x85, 0x08, 0x82, 0x05, 0x82,
+ 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04,
+ 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82, 0x0d, 0x82, 0x04, 0x82, 0x06, 0x82, 0x04, 0x82,
+ 0x04, 0x84, 0x04, 0x82, 0x01, 0x82, 0x01, 0x82, 0x05, 0x82, 0x05, 0x82, 0x04, 0x82, 0x05,
+ 0x82, 0x08, 0x82, 0x08, 0x82, 0x08, 0x82, 0x38, 0x82, 0x01, 0x82, 0x04, 0x82, 0x01, 0x82,
+ 0x01, 0x82, 0x04, 0x84, 0x01, 0x82, 0x01, 0x82, 0x03, 0x82, 0x10, 0x82, 0x08, 0x82, 0x30,
+ 0x83, 0x06, 0x82, 0x07, 0x82, 0x02, 0x82, 0x06, 0x82, 0x05, 0x82, 0x08, 0x82, 0x04, 0x82,
+ 0x07, 0x82, 0x03, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x04, 0x82, 0x06, 0x82, 0x04,
+ 0x82, 0x03, 0x81, 0x04, 0x82, 0x1a, 0x82, 0x10, 0x82, 0x10, 0x82, 0x08, 0x82, 0x04, 0x82,
+ 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08,
+ 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x05, 0x82, 0x05, 0x82, 0x03, 0x82,
+ 0x03, 0x82, 0x03, 0x82, 0x03, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x03, 0x83, 0x02,
+ 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x02, 0x84, 0x02, 0x82, 0x03, 0x82, 0x03, 0x82,
+ 0x04, 0x82, 0x05, 0x82, 0x05, 0x82, 0x04, 0x82, 0x05, 0x82, 0x05, 0x83, 0x02, 0x83, 0x03,
+ 0x82, 0x02, 0x82, 0x06, 0x82, 0x05, 0x82, 0x09, 0x82, 0x0c, 0x82, 0x08, 0x82, 0x21, 0x82,
+ 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x0a,
+ 0x82, 0x07, 0x85, 0x04, 0x82, 0x04, 0x82, 0x05, 0x82, 0x0b, 0x82, 0x02, 0x82, 0x02, 0x82,
+ 0x07, 0x82, 0x05, 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04,
+ 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82, 0x0d, 0x82, 0x04, 0x82,
+ 0x06, 0x82, 0x04, 0x82, 0x04, 0x84, 0x04, 0x82, 0x01, 0x82, 0x01, 0x82, 0x04, 0x84, 0x04,
+ 0x82, 0x04, 0x82, 0x04, 0x82, 0x09, 0x82, 0x08, 0x82, 0x08, 0x82, 0x26, 0x82, 0x10, 0x82,
+ 0x01, 0x82, 0x05, 0x86, 0x04, 0x82, 0x01, 0x82, 0x01, 0x82, 0x01, 0x83, 0x01, 0x84, 0x10,
+ 0x82, 0x06, 0x82, 0x1d, 0x83, 0x11, 0x83, 0x05, 0x82, 0x09, 0x84, 0x07, 0x82, 0x05, 0x82,
+ 0x09, 0x82, 0x02, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04,
+ 0x82, 0x08, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x06, 0x83, 0x07, 0x83, 0x09, 0x82,
+ 0x0e, 0x82, 0x0a, 0x82, 0x06, 0x82, 0x03, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x03,
+ 0x82, 0x04, 0x82, 0x02, 0x82, 0x03, 0x82, 0x03, 0x82, 0x03, 0x82, 0x08, 0x82, 0x09, 0x82,
+ 0x02, 0x83, 0x02, 0x82, 0x04, 0x82, 0x05, 0x82, 0x06, 0x82, 0x01, 0x82, 0x04, 0x82, 0x04,
+ 0x82, 0x02, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82, 0x02, 0x82,
+ 0x03, 0x82, 0x09, 0x82, 0x02, 0x82, 0x03, 0x82, 0x04, 0x82, 0x03, 0x82, 0x02, 0x82, 0x06,
+ 0x82, 0x06, 0x82, 0x02, 0x82, 0x06, 0x82, 0x05, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82,
+ 0x05, 0x82, 0x05, 0x82, 0x09, 0x82, 0x0d, 0x82, 0x07, 0x82, 0x21, 0x82, 0x04, 0x82, 0x02,
+ 0x83, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82, 0x03, 0x82, 0x02, 0x83, 0x03, 0x82, 0x03, 0x82,
+ 0x04, 0x82, 0x06, 0x82, 0x08, 0x82, 0x04, 0x82, 0x05, 0x82, 0x0b, 0x82, 0x02, 0x82, 0x03,
+ 0x82, 0x06, 0x82, 0x05, 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82,
+ 0x02, 0x82, 0x03, 0x83, 0x02, 0x82, 0x04, 0x82, 0x02, 0x83, 0x03, 0x82, 0x07, 0x82, 0x04,
+ 0x82, 0x04, 0x82, 0x02, 0x82, 0x03, 0x82, 0x02, 0x83, 0x05, 0x82, 0x05, 0x88, 0x03, 0x82,
+ 0x02, 0x82, 0x04, 0x82, 0x02, 0x83, 0x03, 0x82, 0x0a, 0x82, 0x08, 0x82, 0x08, 0x82, 0x26,
+ 0x82, 0x1c, 0x82, 0x06, 0x82, 0x02, 0x83, 0x03, 0x84, 0x02, 0x82, 0x10, 0x82, 0x04, 0x82,
+ 0x1e, 0x83, 0x11, 0x83, 0x05, 0x82, 0x0a, 0x82, 0x05, 0x88, 0x02, 0x88, 0x04, 0x84, 0x09,
+ 0x82, 0x05, 0x84, 0x06, 0x84, 0x05, 0x82, 0x09, 0x84, 0x06, 0x84, 0x07, 0x83, 0x07, 0x83,
+ 0x0a, 0x81, 0x0e, 0x81, 0x0b, 0x82, 0x07, 0x85, 0x03, 0x82, 0x04, 0x82, 0x02, 0x86, 0x06,
+ 0x84, 0x04, 0x86, 0x04, 0x88, 0x02, 0x82, 0x0a, 0x84, 0x01, 0x81, 0x02, 0x82, 0x04, 0x82,
+ 0x02, 0x88, 0x04, 0x83, 0x05, 0x82, 0x04, 0x82, 0x02, 0x88, 0x02, 0x82, 0x04, 0x82, 0x02,
+ 0x82, 0x04, 0x82, 0x04, 0x84, 0x04, 0x82, 0x0a, 0x85, 0x03, 0x82, 0x04, 0x82, 0x04, 0x84,
+ 0x07, 0x82, 0x07, 0x84, 0x07, 0x82, 0x05, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x05,
+ 0x82, 0x05, 0x88, 0x03, 0x86, 0x09, 0x82, 0x03, 0x86, 0x22, 0x85, 0x01, 0x81, 0x02, 0x82,
+ 0x01, 0x83, 0x06, 0x85, 0x05, 0x83, 0x01, 0x82, 0x04, 0x85, 0x05, 0x82, 0x07, 0x86, 0x03,
+ 0x82, 0x04, 0x82, 0x02, 0x88, 0x08, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x88, 0x02, 0x82,
+ 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x04, 0x82, 0x04, 0x84, 0x04, 0x82, 0x01, 0x83, 0x06,
+ 0x83, 0x01, 0x82, 0x03, 0x82, 0x08, 0x86, 0x06, 0x84, 0x05, 0x83, 0x01, 0x82, 0x05, 0x82,
+ 0x06, 0x82, 0x02, 0x82, 0x03, 0x82, 0x04, 0x82, 0x04, 0x83, 0x01, 0x82, 0x03, 0x87, 0x06,
+ 0x84, 0x05, 0x82, 0x05, 0x84, 0x7f, 0x15, 0x83, 0x7f, 0x14, 0x83, 0x7f, 0x5e, 0x82, 0x7f,
+ 0x05, 0x89, 0x47, 0x82, 0x04, 0x82, 0x17, 0x82, 0x03, 0x82, 0x34, 0x82, 0x0e, 0x82, 0x4e,
+ 0x82, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x0a, 0x82, 0x04, 0x82, 0x17, 0x82, 0x03, 0x82,
+ 0x34, 0x82, 0x0e, 0x82, 0x48, 0x82, 0x04, 0x82, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x0a,
+ 0x82, 0x04, 0x82, 0x17, 0x82, 0x03, 0x82, 0x34, 0x82, 0x0e, 0x82, 0x49, 0x82, 0x02, 0x82,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x0c, 0x86, 0x19, 0x85, 0x35, 0x82, 0x0e, 0x82, 0x4a,
+ 0x84, 0x3f,
+ 0x00,
+ }
+};
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef UNUSED
+#define UNUSED __attribute__((unused))
+#endif /* UNUSED */
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#endif /* ARRAY_SIZE */
+
+#if __STDC_VERSION__ < 199901L
+#if __GNUC__ >= 2
+#define __func__ __FUNCTION__
+#else
+#define __func__ "<unknown>"
+#endif
+#endif
+
+#define ASSERT_ARRAYS_EQUAL_LENGTH(a1, a2) \
+ _Static_assert(ARRAY_SIZE(a1) == ARRAY_SIZE(a2), \
+ "Arrays " #a1 " and " #a2 " must have equal length.");
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2007 The Android Open Source Project
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+
+#include <linux/fb.h>
+
+#include "graphics.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ int fd,
+ displayed_buffer;
+ gr_surface gr_draw;
+ GRSurface gr_framebuffer[2];
+ struct fb_var_screeninfo vi;
+ struct fb_fix_screeninfo fi;
+} fbdev_common;
+
+bool fbdev_init_common(gr_backend *backend);
+bool fbdev_exit_common(gr_backend *backend);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include "fbdev.h"
+#include "common.h"
+#include "graphics.h"
+
+bool fbdev_init_common(gr_backend *backend)
+{
+ fbdev_common *fb = (fbdev_common *)backend->data;
+
+ memset(fb->gr_framebuffer, 0, sizeof(fb->gr_framebuffer));
+
+ fb->fd = open("/dev/fb0", O_RDWR);
+ if (fb->fd < 0) {
+ perror("Cannot open fb0");
+ return false;
+ }
+
+ if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &fb->vi) < 0) {
+ perror("Failed to get fb0 info");
+ backend->exit(backend);
+ return false;
+ }
+
+ if (ioctl(fb->fd, FBIOGET_FSCREENINFO, &fb->fi) < 0) {
+ printf("Failed to get fb0 fix info");
+ return false;
+ }
+
+ /* If you have a device that has other BPP patches welcome... */
+ if (fb->vi.bits_per_pixel != 32) {
+ printf("Non-32-bit framebuffers not supported yet. Sorry.\n");
+ backend->exit(backend);
+ return false;
+ }
+
+ fb->gr_framebuffer[0].width = fb->vi.xres;
+ fb->gr_framebuffer[0].height = fb->vi.yres;
+ fb->gr_framebuffer[0].pixel_bytes = fb->vi.bits_per_pixel / 8;
+ fb->gr_framebuffer[0].row_bytes = fb->gr_framebuffer[0].width * fb->gr_framebuffer[0].pixel_bytes;
+ memcpy(fb->gr_framebuffer + 1, fb->gr_framebuffer, sizeof(GRSurface));
+ fb->gr_draw = fb->gr_framebuffer + 1;
+ return true;
+}
+
+bool fbdev_exit_common(gr_backend *backend)
+{
+ fbdev_common *fb = (fbdev_common *)backend->data;
+
+ fb->gr_framebuffer[0].data = NULL;
+ fb->gr_framebuffer[1].data = NULL;
+ fb->gr_draw = NULL;
+
+ if (fb->fd != -1 && close(fb->fd) < 0) {
+ perror("Can't close framebuffer descriptor");
+ return false;
+ }
+
+ fb->fd = -1;
+ return true;
+}
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2014 The Android Open Source Project
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#include <linux/fb.h>
+
+#include <sys/mman.h>
+#include <sys/cdefs.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include "fbdev.h"
+#include "common.h"
+#include "graphics.h"
+
+static gr_surface fbdev_init(gr_backend *);
+static gr_surface fbdev_flip(gr_backend *);
+static bool fbdev_exit(gr_backend *);
+
+fbdev_common fb_data = {
+ .fd = -1,
+ .displayed_buffer = 0,
+ .gr_draw = NULL
+};
+
+static gr_backend fbdev_backend = {
+ .init = fbdev_init,
+ .flip = fbdev_flip,
+ .exit = fbdev_exit,
+ .data = (void *)&fb_data
+};
+
+gr_backend *open_fbdev(void)
+{
+ return &fbdev_backend;
+}
+
+static void fbdev_blank(gr_backend *backend, bool blank)
+{
+ int ret;
+ fbdev_common *fb = (fbdev_common *)backend->data;
+
+ ret = ioctl(fb->fd, FBIOBLANK, blank ? FB_BLANK_POWERDOWN :
+ FB_BLANK_UNBLANK);
+ if (ret < 0)
+ perror("ioctl(): blank");
+}
+
+static void set_displayed_framebuffer(fbdev_common *fb, unsigned int n)
+{
+ if (n > 1)
+ return;
+
+ if (n == 0)
+ fb->vi.yoffset = 0;
+ else
+ fb->vi.yoffset = fb->vi.yres;
+
+ if (ioctl(fb->fd, FBIOPUT_VSCREENINFO, &fb->vi) < 0)
+ perror("Active fb swap failed");
+
+ fb->displayed_buffer = n;
+}
+
+static gr_surface fbdev_init(gr_backend *backend)
+{
+ size_t bufsize;
+ size_t bufsize_for_mmap;
+ int nr_buffer;
+
+ fbdev_common *fb = (fbdev_common *)backend->data;
+
+ if (!fbdev_init_common(backend))
+ return NULL;
+
+ nr_buffer = fb->vi.yres_virtual / fb->vi.yres;
+ printf("Frame buffer nr = %d\n", nr_buffer);
+
+ bufsize = fb->fi.line_length * fb->vi.yres;
+ //TODO : Based on Kernel code, following code is right.
+ // : However, it is strange because of bufsize > bufsize_for_mmap
+ // : It should be re-checked later with other kernel's framebuffer.
+ bufsize_for_mmap = fb->vi.xres * fb->vi.yres * fb->vi.bits_per_pixel / 8;
+
+ fb->gr_framebuffer[0].data = mmap(0, bufsize_for_mmap * nr_buffer,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ fb->fd, 0);
+
+ if (fb->gr_framebuffer[0].data == MAP_FAILED) {
+ perror("Failed to mmap video memory");
+ fbdev_exit(backend);
+ return NULL;
+ }
+
+ fb->gr_framebuffer[1].data = fb->gr_framebuffer[0].data + bufsize;
+ gr_fill_alpha(&fb->gr_framebuffer[0]);
+ memcpy(fb->gr_framebuffer[1].data, fb->gr_framebuffer[0].data,
+ bufsize);
+ set_displayed_framebuffer(fb, 0);
+
+ printf("Framebuffer: %dx%d, %d BPP\n", fb->gr_draw->width,
+ fb->gr_draw->height, fb->vi.bits_per_pixel);
+
+ fbdev_blank(backend, true);
+ fbdev_blank(backend, false);
+ return fb->gr_draw;
+}
+
+static gr_surface fbdev_flip(gr_backend *backend)
+{
+ fbdev_common *fb = (fbdev_common *)backend->data;
+
+ /* Change gr_draw to point to the buffer currently displayed,
+ * then flip the driver so we're displaying the other buffer
+ * instead. */
+ fb->gr_draw = fb->gr_framebuffer + fb->displayed_buffer;
+ set_displayed_framebuffer(fb, 1 - fb->displayed_buffer);
+ return fb->gr_draw;
+}
+
+static bool fbdev_exit(gr_backend *backend)
+{
+ fbdev_common *fb = (fbdev_common *)backend->data;
+ size_t bufsize = fb->vi.xres * fb->vi.yres * fb->vi.bits_per_pixel / 8;
+
+ /* Unmap double buffer */
+ if (fb->gr_framebuffer[0].data &&
+ munmap(fb->gr_framebuffer[0].data, bufsize * 2) < 0) {
+ perror("Failed to unmmap video memory");
+ return false;
+ }
+
+ return fbdev_exit_common(backend);
+}
--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil -*-
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/cdefs.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <tdm.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "graphics.h"
+#include "tdm-if.h"
+
+static gr_surface tdm_init(gr_backend *);
+static gr_surface tdm_flip(gr_backend *);
+static bool tdm_exit(gr_backend *);
+
+struct _tdm_data {
+ GRSurface gr_framebuffer;
+};
+
+static struct _tdm_data tdm_data;
+
+static gr_backend tdm_backend = {
+ .init = tdm_init,
+ .flip = tdm_flip,
+ .exit = tdm_exit,
+ .data = (void*)&tdm_data,
+};
+
+gr_backend *open_tdm(void)
+{
+ return &tdm_backend;
+}
+
+gr_surface tdm_init(gr_backend *backend)
+{
+ struct _tdm_data *data = (struct _tdm_data*)backend->data;
+ gr_surface gr_draw = (gr_surface)&data->gr_framebuffer;
+
+ if (tdm_if_display_init() < 0)
+ return NULL;
+
+ tdm_if_lcd_off();
+
+ gr_draw->width = tdm_if_display_width();
+ gr_draw->height = tdm_if_display_height();
+ gr_draw->pixel_bytes = 4; /* XXX */
+ gr_draw->row_bytes = tdm_if_display_stride();
+ gr_draw->data = malloc(tdm_if_display_bufsize());
+ if (gr_draw->data == NULL)
+ return NULL;
+
+ tdm_if_lcd_on();
+ return gr_draw;
+}
+
+gr_surface tdm_flip(gr_backend *backend)
+{
+ struct _tdm_data *data = (struct _tdm_data*)backend->data;
+ gr_surface gr_draw = (gr_surface)&data->gr_framebuffer;
+
+ tdm_if_buffer_update(gr_draw->data);
+ tdm_if_display_update();
+
+ return gr_draw;
+}
+
+bool tdm_exit(gr_backend *backend)
+{
+ struct _tdm_data *data = (struct _tdm_data*)backend->data;
+ gr_surface gr_draw = (gr_surface)&data->gr_framebuffer;
+
+ tdm_if_display_deinit();
+
+ if (gr_draw->data != NULL)
+ free(gr_draw->data);
+
+ return true;
+}
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2007 The Android Open Source Project
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <time.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#include <linux/kd.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include "graphics.h"
+#include "rui-image.h"
+#include "font-10x18.h"
+
+#include "config.h"
+
+typedef struct {
+ gr_surface texture;
+ int cwidth;
+ int cheight;
+} GRFont;
+
+static GRFont *gr_font = NULL;
+static gr_backend *g_backend = NULL;
+
+static color gr_current_color = WHITE;
+static gr_surface gr_draw = NULL;
+
+static bool outside(int x, int y)
+{
+ return x < 0 || x >= gr_draw->width || y < 0 || y >= gr_draw->height;
+}
+
+int gr_get_font_cwidth(void)
+{
+ return gr_font->cwidth;
+}
+
+int gr_get_font_cheight(void)
+{
+ return gr_font->cheight;
+}
+
+void gr_set_color(color c)
+{
+ gr_current_color = c;
+}
+
+void gr_draw_rectangle(int x, int y, int width, int height)
+{
+ int i, j;
+ unsigned char *dst_p, *first_line;
+ color *px;
+
+ if (outside(x, y) || outside(x + width - 1, y + height - 1))
+ return;
+
+ dst_p = gr_draw->data + y * gr_draw->row_bytes +
+ x * gr_draw->pixel_bytes;
+
+ for (i = 0, px = (color *)dst_p; i < width; i++)
+ *px++ = gr_current_color;
+
+ first_line = dst_p;
+ dst_p += gr_draw->row_bytes;
+ for (j = 1; j < height; j++, dst_p += gr_draw->row_bytes)
+ memcpy(dst_p, first_line, width * gr_draw->pixel_bytes);
+}
+
+void gr_clear(void)
+{
+ gr_draw_rectangle(0, 0, gr_draw->width, gr_draw->height);
+}
+
+/* Set Alpha component of pixels to 255 to make overlay visible. */
+void gr_fill_alpha(gr_surface gr)
+{
+ int i, j;
+ unsigned char *dst_p, *first_line;
+ color *px;
+
+ dst_p = gr->data;
+ for (i = 0, px = (color *)dst_p; i < gr->width; i++)
+ *px++ = BLACK;
+
+ first_line = dst_p;
+ dst_p += gr->row_bytes;
+ for (j = 1; j < gr->height; j++, dst_p += gr->row_bytes)
+ memcpy(dst_p, first_line, gr->width * gr->pixel_bytes);
+}
+
+static void gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy)
+{
+ int i;
+ unsigned char *src_p, *dst_p;
+
+ if (!source)
+ return;
+
+ if (gr_draw->pixel_bytes != source->pixel_bytes) {
+ printf("%s: source has wrong format: %d bytes per pixel\n",
+ __func__, source->pixel_bytes);
+ return;
+ }
+
+ if (outside(dx, dy) || outside(dx + w - 1, dy + h - 1))
+ return;
+
+ src_p = source->data + sy * source->row_bytes +
+ sx * source->pixel_bytes;
+ dst_p = gr_draw->data + dy * gr_draw->row_bytes +
+ dx * gr_draw->pixel_bytes;
+
+ for (i = 0; i < h; ++i) {
+ memcpy(dst_p, src_p, w * source->pixel_bytes);
+ src_p += source->row_bytes;
+ dst_p += gr_draw->row_bytes;
+ }
+}
+
+/* RGB + Alpha */
+static void gr_blend_rgba(gr_surface source, int w, int h, unsigned char *src_p,
+ unsigned char *dst_p)
+{
+ int i, j;
+
+ for (j = 0; j < h; j++) {
+ color *sx = (color *)src_p;
+ color *px = (color *)dst_p;
+
+ for (i = 0; i < w; i++) {
+ unsigned char r = sx->r, g = sx->g, b = sx->b,
+ a = sx->a;
+
+ if (a == 255) {
+ *px++ = *sx;
+ } else {
+ px->r = (px->r * (255 - a) + r * a) / 255;
+ px->g = (px->g * (255 - a) + g * a) / 255;
+ px->b = (px->b * (255 - a) + b * a) / 255;
+ px->a = 255;
+ }
+ }
+
+ src_p += source->row_bytes;
+ dst_p += gr_draw->row_bytes;
+ }
+}
+
+/* RGB: Using current color's Alpha as alpha */
+static void gr_blend_rgb(gr_surface source, int w, int h, unsigned char *src_p,
+ unsigned char *dst_p)
+{
+ int i, j;
+
+ for (j = 0; j < h; j++) {
+ color *sx = (color *)src_p;
+ color *px = (color *)dst_p;
+
+ for (i = 0; i < w; i++) {
+ unsigned char r = sx->r, g = sx->g, b = sx->b;
+
+ if (gr_current_color.a == 255) {
+ *px = *sx;
+ px->a = 255;
+ px++;
+ } else {
+ px->r = (px->r * (255 - gr_current_color.a) +
+ r * gr_current_color.a) / 255;
+ px->g = (px->g * (255 - gr_current_color.a) +
+ g * gr_current_color.a) / 255;
+ px->b = (px->b * (255 - gr_current_color.a) +
+ b * gr_current_color.a) / 255;
+ px->a = 255;
+ px++;
+ }
+ }
+
+ src_p += source->row_bytes;
+ dst_p += gr_draw->row_bytes;
+ }
+}
+
+/* Grayscale + Alpha */
+static void gr_blend_ga(gr_surface source, int w, int h, unsigned char *src_p,
+ unsigned char *dst_p)
+{
+ int i, j;
+
+ for (j = 0; j < h; j++) {
+ unsigned char *sx = src_p;
+ color *px = (color *)dst_p;
+
+ for (i = 0; i < w; i++) {
+ unsigned char gr = *sx++, a = *sx++;
+
+ if (a == 255) {
+ px->r = gr;
+ px->g = gr;
+ px->b = gr;
+ px->a = 255;
+ px++;
+ } else {
+ px->r = (px->r * (255 - a) + gr * a) / 255;
+ px->g = (px->g * (255 - a) + gr * a) / 255;
+ px->b = (px->b * (255 - a) + gr * a) / 255;
+ px->a = 255;
+ ++px;
+ }
+ }
+
+ src_p += source->row_bytes;
+ dst_p += gr_draw->row_bytes;
+ }
+}
+
+/* Grayscale.
+ * Using image as Alpha channel and current color for foreground. */
+static void gr_blend_g(gr_surface source, int w, int h, unsigned char *src_p,
+ unsigned char *dst_p)
+{
+ int i, j;
+
+ for (j = 0; j < h; j++) {
+ unsigned char *sx = src_p;
+ color *px = (color *)dst_p;
+
+ for (i = 0; i < w; i++) {
+ unsigned char a = *sx++;
+
+ if (gr_current_color.a < 255)
+ a = ((int)a * gr_current_color.a) / 255;
+
+ if (a == 255) {
+ *px = gr_current_color;
+ px++;
+ } else {
+ px->r = (px->r * (255 - a) +
+ gr_current_color.r * a) / 255;
+ px->g = (px->g * (255 - a) +
+ gr_current_color.g * a) / 255;
+ px->b = (px->b * (255 - a) +
+ gr_current_color.b * a) / 255;
+ px->a = 255;
+ ++px;
+ }
+ }
+
+ src_p += source->row_bytes;
+ dst_p += gr_draw->row_bytes;
+ }
+}
+
+static void gr_blend(gr_surface source, int sx, int sy, int w, int h, int dx, int dy)
+{
+ unsigned char *src_p, *dst_p;
+
+ if (!source)
+ return;
+
+ if (outside(dx, dy) || outside(dx + w - 1, dy + h - 1))
+ return;
+
+ src_p = source->data + sy * source->row_bytes +
+ sx * source->pixel_bytes;
+ dst_p = gr_draw->data + dy * gr_draw->row_bytes +
+ dx * gr_draw->pixel_bytes;
+
+ if (source->pixel_bytes == 4)
+ gr_blend_rgba(source, w, h, src_p, dst_p);
+ else if (source->pixel_bytes == 3)
+ gr_blend_rgb(source, w, h, src_p, dst_p);
+ else if (source->pixel_bytes == 2)
+ gr_blend_ga(source, w, h, src_p, dst_p);
+ else if (source->pixel_bytes == 1)
+ gr_blend_g(source, w, h, src_p, dst_p);
+ else
+ printf("%s: source has wrong format: %d bytes per pixel\n",
+ __func__, source->pixel_bytes);
+}
+
+void gr_text(int x, int y, const char *s, gr_font_style style)
+{
+ GRFont *font = gr_font;
+ unsigned int off;
+ int start_x = x;
+
+ if (!font->texture || !s)
+ return;
+
+ if (gr_current_color.a == 0)
+ return;
+
+ if (style == GR_FONT_BOLD && font->texture->height == font->cheight)
+ style = GR_FONT_REGULAR; /* No bold font in image */
+
+ while ((off = *s++)) {
+ unsigned char *src_p, *dst_p;
+
+ if (off == '\n') {
+ x = start_x;
+ y += font->cheight;
+ continue;
+ }
+
+ if (outside(x, y) ||
+ outside(x + font->cwidth - 1, y + font->cheight - 1))
+ continue;
+
+ off -= 32;
+ if (off >= 96)
+ off = '_' - 32; /* Replacement for unknown symbols */
+
+ src_p = font->texture->data + off * font->cwidth +
+ (style == GR_FONT_BOLD ?
+ font->cheight * font->texture->row_bytes : 0);
+ dst_p = gr_draw->data + y * gr_draw->row_bytes +
+ x * gr_draw->pixel_bytes;
+ gr_blend_g(font->texture, font->cwidth, font->cheight, src_p,
+ dst_p);
+
+ x += font->cwidth;
+ }
+}
+
+static void gr_align_surface(gr_surface surface, int *posX, int *posY,
+ gr_align_horizontal xalign, gr_align_vertical yalign,
+ int offset_x, int offset_y)
+{
+ if (xalign == GR_ALIGN_LEFT)
+ *posX = 0;
+ else if (xalign == GR_ALIGN_CENTER)
+ *posX = (gr_fb_width() - gr_get_width(surface)) / 2;
+ else
+ *posX = gr_fb_width() - gr_get_width(surface);
+
+ if (yalign == GR_ALIGN_TOP)
+ *posY = 0;
+ else if (yalign == GR_ALIGN_MIDDLE)
+ *posY = (gr_fb_height() - gr_get_height(surface)) / 2;
+ else
+ *posY = gr_fb_height() - gr_get_height(surface);
+
+ *posX += offset_x;
+ *posY += offset_y;
+}
+
+void gr_blend_image_aligned(gr_surface source, gr_align_horizontal xalign,
+ gr_align_vertical yalign, int offset_x, int offset_y)
+{
+ int posX, posY;
+
+ gr_align_surface(source, &posX, &posY, xalign, yalign, offset_x,
+ offset_y);
+ gr_blend(source, 0, 0, gr_get_width(source), gr_get_height(source),
+ posX, posY);
+}
+
+void gr_blit_image_aligned(gr_surface source, gr_align_horizontal xalign,
+ gr_align_vertical yalign, int offset_x, int offset_y)
+{
+ int posX, posY;
+
+ gr_align_surface(source, &posX, &posY, xalign, yalign, offset_x,
+ offset_y);
+ gr_blit(source, 0, 0, gr_get_width(source), gr_get_height(source),
+ posX, posY);
+}
+
+unsigned int gr_get_width(gr_surface surface)
+{
+ if (!surface)
+ return 0;
+
+ return surface->width;
+}
+
+unsigned int gr_get_height(gr_surface surface)
+{
+ if (!surface)
+ return 0;
+
+ return surface->height;
+}
+
+static void gr_init_font(void)
+{
+ int res;
+
+ gr_font = calloc(sizeof(*gr_font), 1);
+ if (gr_font == NULL) {
+ printf("%s:%d: Memory allocation has failed.", __FILE__, __LINE__);
+ return;
+ }
+
+ res = res_create_image_surface(RUI_IMAGES_DIR "/font.png",
+ &(gr_font->texture), GR_WITH_ALPHA);
+ if (res == 0) {
+ /* The font image should be a 96x2 array of character images.
+ * The columns are the printable ASCII characters 0x20 - 0x7f.
+ * The top row is regular text; the bottom row is bold. */
+ gr_font->cwidth = gr_font->texture->width / 96;
+ gr_font->cheight = gr_font->texture->height / 2;
+ } else {
+ unsigned char *bits, *in, data;
+
+ printf("Failed to read font: res=%d\n", res);
+
+ /* fall back to the compiled-in font. */
+ gr_font->texture = malloc(sizeof(*gr_font->texture));
+ if (gr_font->texture == NULL) {
+ printf("%s:%d: Memory allocation has failed.", __FILE__, __LINE__);
+ free(gr_font);
+ return;
+ }
+ gr_font->texture->width = font.width;
+ gr_font->texture->height = font.height;
+ gr_font->texture->row_bytes = font.width;
+ gr_font->texture->pixel_bytes = 1;
+
+ bits = malloc(font.width * font.height);
+ gr_font->texture->data = (void *)bits;
+
+ in = font.rundata;
+ while ((data = *in++)) {
+ memset(bits, (data & 0x80) ? 255 : 0, data & 0x7f);
+ bits += (data & 0x7f);
+ }
+
+ gr_font->cwidth = font.cwidth;
+ gr_font->cheight = font.cheight;
+ }
+}
+
+void gr_flip(void)
+{
+ gr_draw = g_backend->flip(g_backend);
+}
+
+bool gr_init(void)
+{
+ gr_init_font();
+
+#ifdef HAVE_TDM
+ g_backend = open_tdm();
+#else
+ g_backend = open_fbdev();
+#endif
+ gr_draw = g_backend->init(g_backend);
+ if (gr_draw == NULL)
+ return false;
+
+ gr_flip();
+ gr_flip();
+
+ return true;
+}
+
+void gr_exit(void)
+{
+ g_backend->exit(g_backend);
+}
+
+int gr_fb_width(void)
+{
+ return gr_draw->width;
+}
+
+int gr_fb_height(void)
+{
+ return gr_draw->height;
+}
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2007 The Android Open Source Project
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+
+#include <sys/types.h>
+
+#include "config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ int width;
+ int height;
+ int row_bytes;
+ int pixel_bytes;
+ unsigned char *data;
+} GRSurface;
+
+typedef GRSurface *gr_surface;
+
+typedef struct gr_backend {
+ /* Initializes the backend and returns a gr_surface to draw into. */
+ gr_surface(*init)(struct gr_backend *);
+
+ /* Causes the current drawing surface (returned by the most recent
+ * call to flip() or init()) to be displayed, and returns a new
+ * drawing surface. */
+ gr_surface(*flip)(struct gr_backend *);
+
+ /* Device cleanup when drawing is done. */
+ bool (*exit)(struct gr_backend *);
+
+ void *data; /* Private data for graphics backend */
+} gr_backend;
+
+#ifdef HAVE_TDM /* BGRA */
+typedef struct {
+ unsigned char b, g, r, a;
+} color;
+
+gr_backend *open_tdm(void);
+
+#else /* RGBA */
+typedef struct {
+ unsigned char r, g, b, a;
+} color;
+
+gr_backend *open_fbdev(void);
+#endif
+
+#define BLACK (color) { .r = 0, .g = 0, .b = 0, .a = 255 }
+#define RED (color) { .r = 255, .g = 0, .b = 0, .a = 255 }
+#define GREEN (color) { .r = 0, .g = 255, .b = 0, .a = 255 }
+#define YELLOW (color) { .r = 255, .g = 255, .b = 0, .a = 255 }
+#define BLUE (color) { .r = 0, .g = 0, .b = 255, .a = 255 }
+#define MAGENTA (color) { .r = 255, .g = 0, .b = 255, .a = 255 }
+#define CYAN (color) { .r = 0, .g = 255, .b = 255, .a = 255 }
+#define WHITE (color) { .r = 255, .g = 255, .b = 255, .a = 255 }
+
+bool gr_init(void);
+void gr_exit(void);
+
+int gr_fb_width(void);
+int gr_fb_height(void);
+
+void gr_flip(void);
+
+void gr_fill_alpha(gr_surface gr);
+void gr_clear(); /* Clear entire surface to current color */
+void gr_set_color(color c); /* Set current color */
+void gr_draw_rectangle(int x, int y, int width, int height);
+
+typedef enum {
+ GR_FONT_REGULAR,
+ GR_FONT_BOLD
+} gr_font_style;
+
+void gr_text(int x, int y, const char *s, gr_font_style style);
+int gr_get_font_cwidth(void);
+int gr_get_font_cheight(void);
+
+typedef enum {
+ GR_ALIGN_LEFT,
+ GR_ALIGN_CENTER,
+ GR_ALIGN_RIGHT
+} gr_align_horizontal;
+
+typedef enum {
+ GR_ALIGN_TOP,
+ GR_ALIGN_MIDDLE,
+ GR_ALIGN_BOTTOM
+} gr_align_vertical;
+
+void gr_blit_image_aligned(gr_surface source, gr_align_horizontal xalign,
+ gr_align_vertical yalign, int offset_x,
+ int offset_y);
+void gr_blend_image_aligned(gr_surface source, gr_align_horizontal xalign,
+ gr_align_vertical yalign, int offset_x,
+ int offset_y);
+
+unsigned int gr_get_width(gr_surface surface);
+unsigned int gr_get_height(gr_surface surface);
+
+typedef enum {
+ GR_WITHOUT_ALPHA,
+ GR_WITH_ALPHA
+} gr_img_type;
+
+/* Load a single display surface from a PNG image. */
+int res_create_image_surface(const char *name, gr_surface *pSurface,
+ gr_img_type img_type);
+
+/* Load an array of display surfaces from a single PNG image. The PNG
+ * should have a "Frames" text chunk whose value is the number of
+ * frames this image represents. The pixel data itself is interlaced
+ * by row. */
+int res_create_anim_image_surfaces(const char *name, int *frames,
+ gr_surface **pSurface,
+ gr_img_type img_type);
+
+/* Load part of a grayscale PNG image that is the first match for the
+ * given locale. The image is expected to be a composite of multiple
+ * translations of the same text, with special added rows that encode
+ * the subimages' size and intended locale in the pixel data. */
+int res_create_localized_alpha_surface(const char *name, const char *locale,
+ gr_surface *pSurface);
+
+/* Free a surface allocated by any of the res_create_*_surface()
+ * functions. */
+void res_free_surface(gr_surface surface);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2007 The Android Open Source Project
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _POSIX_C_SOURCE 200809L
+
+#include <time.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#include <sys/poll.h>
+#include <sys/signalfd.h>
+#include <sys/timerfd.h>
+
+#include <linux/input.h>
+
+#include "input-events.h"
+
+#define MAX_INPUTS 32
+
+#define BITS_PER_LONG (sizeof(unsigned long) * 8)
+#define BITS_TO_LONGS(x) (((x) + BITS_PER_LONG - 1) / BITS_PER_LONG)
+
+#define test_bit(bit, array) \
+ ((array)[(bit) / BITS_PER_LONG] & (1 << ((bit) % BITS_PER_LONG)))
+
+static struct pollfd ev_fds[MAX_INPUTS];
+
+static unsigned ev_count = 0;
+
+static unsigned signalfd_idx = -1;
+static unsigned timerfd_idx = -1;
+
+#define IS_SIGNAL_EVENT(x) (x == signalfd_idx)
+#define IS_TIMER_EVENT(x) (x == timerfd_idx)
+
+static bool ev_signal_init(void)
+{
+ sigset_t mask;
+
+ if (ev_count >= MAX_INPUTS)
+ return false;
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGINT);
+ if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
+ perror("sigprocmask");
+ return false;
+ }
+
+ ev_fds[ev_count].fd = signalfd(-1, &mask, 0);
+ ev_fds[ev_count].events = POLLIN;
+ if (ev_fds[ev_count].fd == -1) {
+ perror("signalfd");
+ return false;
+ }
+ signalfd_idx = ev_count++;
+
+ return true;
+}
+
+static bool ev_timer_init(void)
+{
+ int fd;
+ struct itimerspec timer_spec = {
+ .it_interval = {TIMER_INTERVAL, 0},
+ .it_value = {0, 1},
+ };
+
+ if (ev_count >= MAX_INPUTS)
+ return false;
+
+ fd = timerfd_create(CLOCK_REALTIME, 0);
+ if (fd < 0) {
+ perror("timerfd_create");
+ return false;
+ }
+
+ timerfd_settime(fd, 0, &timer_spec, NULL);
+ ev_fds[ev_count].fd = fd;
+ ev_fds[ev_count].events = POLLIN;
+ timerfd_idx = ev_count++;
+
+ return true;
+}
+
+static bool ev_input_init(void)
+{
+ DIR *dir;
+ struct dirent *de;
+ int fd;
+ int t = ev_count;
+
+ dir = opendir("/dev/input");
+ if (!dir) {
+ printf("Can't open directory \"/dev/input\".\n");
+ return false;
+ }
+
+ while ((de = readdir(dir))) {
+ unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)];
+
+ /* fprintf(stderr,"/dev/input/%s\n", de->d_name);*/
+ if (strncmp(de->d_name, "event", 5))
+ continue;
+
+ fd = openat(dirfd(dir), de->d_name, O_RDONLY);
+ if (fd < 0)
+ continue;
+
+ /* read the evbits of the input device */
+ if (ioctl(fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) < 0) {
+ close(fd);
+ continue;
+ }
+
+ /* TODO: add ability to specify event masks. For now, just
+ * assume that only EV_KEY and EV_REL event types are ever
+ * needed. */
+ if (!test_bit(EV_KEY, ev_bits) && !test_bit(EV_REL, ev_bits)) {
+ close(fd);
+ continue;
+ }
+
+ ev_fds[ev_count].fd = fd;
+ ev_fds[ev_count].events = POLLIN;
+ ev_count++;
+ if (ev_count == MAX_INPUTS)
+ break;
+ }
+
+ closedir(dir);
+ if (ev_count == t) {
+ printf("No input devices found.\n");
+ return false;
+ }
+
+ return true;
+}
+
+bool ev_init(void)
+{
+ return ev_input_init() && ev_signal_init() && ev_timer_init();
+}
+
+void ev_exit(void)
+{
+ while (ev_count > 0)
+ close(ev_fds[--ev_count].fd);
+}
+
+static user_action last_action = ACTION_NONE;
+static time_t event_start = 0;
+
+static void ev_input_longpress_check(input_callback callback)
+{
+ if (event_start && time(NULL) - event_start >= LONGPRESS_TIME) {
+ callback(last_action, ACTION_TYPE_LONGPRESS);
+ event_start = time(NULL); /* Restarting the event */
+ }
+}
+
+static bool ev_input_process(struct input_event *ev, input_callback callback)
+{
+ user_action action = ACTION_NONE;
+
+ ev_input_longpress_check(callback);
+
+ if (!ev) { /* Timeout */
+ callback(ACTION_NONE, ACTION_TYPE_IDLE);
+ return true;
+ }
+
+ if (ev->type == EV_SYN)
+ return true;
+ else if (ev->type == EV_KEY && ev->code <= KEY_MAX) {
+ switch (ev->code) {
+ case KEY_DOWN:
+ case KEY_VOLUMEDOWN:
+ action = ACTION_DOWN;
+ break;
+ case KEY_UP:
+ case KEY_VOLUMEUP:
+ action = ACTION_UP;
+ break;
+ case KEY_ENTER:
+ case KEY_POWER:
+ action = ACTION_CONFIRM;
+ break;
+ case KEY_MENU:
+ action = ACTION_HOME;
+ break;
+ case KEY_PHONE:
+ action = ACTION_MENU;
+ break;
+ case KEY_BACK:
+ action = ACTION_BACK;
+ break;
+ default:
+ /* printf("Unknown key %d.\n", ev->code);*/
+ break;
+ }
+
+ if (action != ACTION_NONE) {
+ if (ev->value == 1) {
+ last_action = action;
+ event_start = time(NULL);
+ } else if (action == last_action) {
+ last_action = ACTION_NONE;
+ event_start = 0;
+ }
+
+ if (callback)
+ callback(action, ev->value == 1 ?
+ ACTION_TYPE_BEGIN :
+ ACTION_TYPE_END);
+ }
+ } else if (ev->type == EV_REL) { /* Relative event */
+
+ } else if (ev->type == EV_ABS) { /* Absolute event */
+
+ }
+
+ return true;
+}
+
+static int ev_wait(int timeout)
+{
+ int ret;
+
+ if ((ret = poll(ev_fds, ev_count, timeout)) < 0)
+ perror("poll()");
+
+ return ret;
+}
+
+bool ev_dispatch(input_callback callback)
+{
+ int r;
+ unsigned n;
+
+ r = ev_wait(DISPATCH_TIMEOUT);
+ if (r < 0)
+ return false;
+ else if (r == 0) /* Timeout */
+ return ev_input_process(NULL, callback);
+
+ for (n = 0; n < ev_count; n++)
+ if (ev_fds[n].revents & POLLIN) {
+ int r;
+ struct input_event ev;
+
+ if (IS_SIGNAL_EVENT(n)) { /* signalfd */
+ struct signalfd_siginfo fdsi;
+ r = read(ev_fds[n].fd, &fdsi, sizeof(fdsi));
+ if (r != sizeof(fdsi)) {
+ perror("read");
+ return false;
+ }
+ if (fdsi.ssi_signo == SIGINT)
+ return false;
+ continue;
+ }
+
+ if (IS_TIMER_EVENT(n)) {
+ uint64_t exp;
+
+ r = read(ev_fds[n].fd, &exp, sizeof(exp));
+ if (r != sizeof(exp)) {
+ perror("read");
+ return false;
+ }
+
+ callback(ACTION_TIMEOUT, ACTION_TYPE_TIMER);
+ continue;
+ }
+
+ r = read(ev_fds[n].fd, &ev, sizeof(ev));
+ if (r != sizeof(ev))
+ continue;
+
+ if (!ev_input_process(&ev, callback))
+ return false;
+ }
+
+ return true;
+}
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DISPATCH_TIMEOUT (1 * 1000) /* One second */
+#define LONGPRESS_TIME 3 /* Seconds */
+#define TIMER_INTERVAL 1 /* Seconds */
+
+typedef enum {
+ ACTION_NONE,
+ ACTION_DOWN,
+ ACTION_UP,
+ ACTION_CONFIRM,
+ ACTION_HOME,
+ ACTION_MENU,
+ ACTION_BACK,
+ ACTION_TIMEOUT,
+} user_action;
+
+typedef enum {
+ ACTION_TYPE_IDLE,
+ ACTION_TYPE_BEGIN,
+ ACTION_TYPE_END,
+ ACTION_TYPE_LONGPRESS,
+ ACTION_TYPE_TIMER,
+} user_action_type;
+
+typedef void (*input_callback)(user_action action,
+ user_action_type action_type);
+
+bool ev_init(void);
+bool ev_dispatch(input_callback callback);
+void ev_exit(void);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2007 The Android Open Source Project
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <png.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <linux/fb.h>
+#include <linux/kd.h>
+
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include "graphics.h"
+
+extern char *locale;
+
+#define SURFACE_DATA_ALIGNMENT 8
+
+static gr_surface malloc_surface(size_t data_size)
+{
+ gr_surface surface;
+ unsigned char *temp;
+
+ temp = malloc(sizeof(GRSurface) + data_size + SURFACE_DATA_ALIGNMENT);
+ if (!temp)
+ return NULL;
+
+ surface = (gr_surface)temp;
+ surface->data = temp + sizeof(GRSurface) + (SURFACE_DATA_ALIGNMENT -
+ (sizeof(GRSurface) % SURFACE_DATA_ALIGNMENT));
+ return surface;
+}
+
+static int open_png(const char *name,
+ png_structp *png_ptr,
+ png_infop *info_ptr,
+ png_uint_32 *width,
+ png_uint_32 *height,
+ png_byte *channels)
+{
+ unsigned char header[8];
+ int result = 0, color_type, bit_depth;
+ size_t bytesRead;
+ FILE *fp;
+
+ fp = fopen(name, "rb");
+ if (fp == NULL) {
+ result = -1;
+ goto exit2;
+ }
+
+ bytesRead = fread(header, 1, sizeof(header), fp);
+ if (bytesRead != sizeof(header)) {
+ result = -2;
+ goto exit2;
+ }
+
+ if (png_sig_cmp(header, 0, sizeof(header))) {
+ result = -3;
+ goto exit2;
+ }
+
+ *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL,
+ NULL);
+ if (!*png_ptr) {
+ result = -4;
+ goto exit1;
+ }
+
+ *info_ptr = png_create_info_struct(*png_ptr);
+ if (!*info_ptr) {
+ png_destroy_read_struct(png_ptr, NULL, NULL);
+ result = -5;
+ goto exit2;
+ }
+
+ if (setjmp(png_jmpbuf(*png_ptr))) {
+ result = -6;
+ goto exit1;
+ }
+
+ png_init_io(*png_ptr, fp);
+ png_set_sig_bytes(*png_ptr, sizeof(header));
+ png_read_info(*png_ptr, *info_ptr);
+
+ png_get_IHDR(*png_ptr, *info_ptr, width, height, &bit_depth,
+ &color_type, NULL, NULL, NULL);
+
+ *channels = png_get_channels(*png_ptr, *info_ptr);
+
+ if (bit_depth == 8 && *channels == 3 &&
+ color_type == PNG_COLOR_TYPE_RGB) {
+ /* 8-bit RGB: great, nothing to do. */
+ } else if (bit_depth == 8 && *channels == 4 &&
+ color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
+ /* 8-bit RGB with alpha: great, nothing to do. */
+ } else if (bit_depth == 8 && *channels == 2 &&
+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
+ /* 8-bit gray with alpha: great, nothing to do. */
+ } else if (bit_depth == 8 && *channels == 1 &&
+ color_type == PNG_COLOR_TYPE_GRAY) {
+ /* 8-bit gray with: great, nothing to do. */
+ } else if (bit_depth < 8 && *channels == 2 &&
+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
+ /* 1-, 2- or 4-bit gray with alpha: expand to 8-bit gray. */
+ png_set_expand_gray_1_2_4_to_8(*png_ptr);
+ } else if (bit_depth < 8 && *channels == 1 &&
+ color_type == PNG_COLOR_TYPE_GRAY) {
+ /* 1-, 2- or 4-bit gray: expand to 8-bit gray. */
+ png_set_expand_gray_1_2_4_to_8(*png_ptr);
+ } else if (bit_depth <= 8 && *channels == 1 &&
+ color_type == PNG_COLOR_TYPE_PALETTE) {
+ int color_num;
+ png_colorp palette;
+
+ if (png_get_PLTE(*png_ptr, *info_ptr, &palette,
+ &color_num)) {
+ int i, rgb = 0;
+
+ for (i = 0; i < color_num; i++)
+ if (palette[i].red != palette[i].green ||
+ palette[i].red != palette[i].blue) {
+ rgb = 1;
+ break;
+ }
+
+ if (!rgb) {
+ png_set_rgb_to_gray_fixed(*png_ptr, 1, -1, -1);
+ *channels = 1;
+ } else
+ *channels = 3;
+
+ /* paletted images: expand to 8-bit RGB. */
+ png_set_palette_to_rgb(*png_ptr);
+
+ /* Expand paletted or RGB images with transparency to full
+ * alpha channels so the data will be available as RGBA
+ * quartets. */
+ if (*channels == 3 &&
+ png_get_valid(*png_ptr, *info_ptr, PNG_INFO_tRNS)) {
+ png_set_tRNS_to_alpha(*png_ptr);
+ *channels = 4;
+ }
+ }
+ } else {
+ fprintf(stderr,
+ "RUI doesn't support PNG depth %d channels %d "
+ "color_type %d of image \"%s\"\n",
+ bit_depth, *channels, color_type, name);
+ result = -7;
+ goto exit1;
+ }
+
+ return result;
+
+exit1:
+ if (result < 0)
+ png_destroy_read_struct(png_ptr, info_ptr, NULL);
+
+exit2:
+ if (fp != NULL)
+ fclose(fp);
+
+ return result;
+}
+
+/* "display" surfaces are transformed into the framebuffer's required
+ * pixel format (currently only RGBX is supported) at load time, so
+ * gr_blit() can be nothing more than a memcpy() for each row. The
+ * next two functions are the only ones that know anything about the
+ * framebuffer pixel format; they need to be modified if the
+ * framebuffer format changes (but nothing else should). */
+
+/* Allocate and return a gr_surface sufficient for storing an image of
+ * the indicated size in the framebuffer pixel format. */
+static gr_surface init_display_surface(png_uint_32 width, png_uint_32 height, int channels)
+{
+ gr_surface surface;
+
+ if (!(surface = malloc_surface(width * height * channels)))
+ return NULL;
+
+ surface->width = width;
+ surface->height = height;
+ surface->row_bytes = width * channels;
+ surface->pixel_bytes = channels;
+
+ return surface;
+}
+
+/* Copy 'input_row' to 'output_row', transforming it to the
+ * framebuffer pixel format. The input format depends on the value of
+ * 'channels':
+ *
+ * 1 - input is 8-bit grayscale
+ * 2 - input is 8-bit grayscale + 8-bit alpha
+ * 3 - input is 24-bit RGB
+ * 4 - input is 32-bit RGBA/RGBX
+ *
+ * 'width' is the number of pixels in the row. */
+static void transform_rgb_to_draw(unsigned char *input_row,
+ unsigned char *output_row,
+ int channels,
+ int width)
+{
+ int x;
+ unsigned char *ip = input_row, *op = output_row;
+
+ switch (channels) {
+ case 1: /* expand gray level to RGBX */
+ for (x = 0; x < width; x++) {
+ *op++ = *ip;
+ *op++ = *ip;
+ *op++ = *ip++;
+ *op++ = 0xff;
+ }
+
+ break;
+ case 2: /* expand gray level plus alpha to RGBX */
+ for (x = 0; x < width; ++x) {
+ *op++ = *ip;
+ *op++ = *ip;
+ *op++ = *ip++;
+ *op++ = *ip++;
+ }
+
+ break;
+ case 3: /* expand RGBA to RGBX */
+ for (x = 0; x < width; ++x) {
+ *op++ = *ip++;
+ *op++ = *ip++;
+ *op++ = *ip++;
+ *op++ = 0xff;
+ }
+
+ break;
+ case 4: /* copy RGBA to RGBX */
+ memcpy(output_row, input_row, width * 4);
+ break;
+ }
+}
+
+int res_create_anim_image_surfaces(const char *name, int *frames,
+ gr_surface **pSurface, gr_img_type img_type)
+{
+ int result = 0, i, num_text;
+ unsigned char *p_row = NULL;
+ unsigned int y;
+ gr_surface *surface = NULL;
+ png_structp png_ptr = NULL;
+ png_infop info_ptr = NULL;
+ png_uint_32 width, height;
+ png_byte channels;
+ png_textp text;
+
+ *pSurface = NULL;
+ *frames = -1;
+
+ result = open_png(name, &png_ptr, &info_ptr, &width, &height,
+ &channels);
+ if (result < 0) {
+ printf("Can't load image \"%s\": %d.\n", name, result);
+ return result;
+ }
+
+ *frames = 1;
+
+ if (png_get_text(png_ptr, info_ptr, &text, &num_text))
+ for (i = 0; i < num_text; i++)
+ if (text[i].key && !strcmp(text[i].key, "Frames") &&
+ text[i].text) {
+ *frames = atoi(text[i].text);
+ break;
+ }
+
+ if (*frames <= 0) {
+ printf("Bad frame count (%d)\n", *frames);
+ result = -9;
+ goto exit;
+ }
+
+ if (height % *frames || height < *frames) {
+ printf("Bad image height (%d) for frame count (%d)\n",
+ (int)height, *frames);
+ result = -9;
+ goto exit;
+ }
+
+ if (!(surface = malloc(*frames * sizeof(gr_surface)))) {
+ result = -8;
+ goto exit;
+ }
+
+ for (i = 0; i < *frames; i++)
+ if (!(surface[i] = init_display_surface(width,
+ height / *frames,
+ (img_type == GR_WITH_ALPHA ?
+ channels : 4)))) {
+ result = -8;
+ goto exit;
+ }
+
+ if (img_type == GR_WITHOUT_ALPHA)
+ p_row = malloc(width * channels);
+
+ for (y = 0; y < height; y++) {
+ int frame = y % *frames;
+ unsigned char *p_dst = surface[frame]->data + (y / *frames) *
+ surface[frame]->row_bytes;
+
+ if (img_type == GR_WITH_ALPHA)
+ png_read_row(png_ptr, p_dst, NULL);
+ else {
+ png_read_row(png_ptr, p_row, NULL);
+ transform_rgb_to_draw(p_row, p_dst, channels, width);
+ }
+ }
+
+ if (img_type == GR_WITHOUT_ALPHA)
+ free(p_row);
+
+ *pSurface = (gr_surface *)surface;
+
+exit:
+ if (png_get_io_ptr(png_ptr))
+ fclose((FILE *)png_get_io_ptr(png_ptr));
+
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+
+ if (result < 0 && surface) {
+ for (i = 0; i < *frames; i++)
+ if (surface[i])
+ free(surface[i]);
+
+ free(surface);
+ }
+
+ return result;
+}
+
+int res_create_image_surface(const char *name, gr_surface *pSurface,
+ gr_img_type img_type)
+{
+ gr_surface surface = NULL;
+ int result = 0;
+ png_structp png_ptr = NULL;
+ png_infop info_ptr = NULL;
+ png_uint_32 width, height;
+ png_byte channels;
+ unsigned char *p_row = NULL;
+ unsigned int y;
+
+ *pSurface = NULL;
+
+ result = open_png(name, &png_ptr, &info_ptr, &width, &height,
+ &channels);
+ if (result < 0) {
+ printf("Can't load image \"%s\": %d.\n", name, result);
+ return result;
+ }
+
+ if (!(surface = init_display_surface(width, height,
+ (img_type == GR_WITH_ALPHA ?
+ channels : 4)))) {
+ result = -8;
+ goto exit;
+ }
+
+ if (img_type == GR_WITHOUT_ALPHA)
+ p_row = malloc(width * channels);
+
+ for (y = 0; y < height; y++) {
+ unsigned char *p_dst = surface->data + y * surface->row_bytes;
+
+ if (img_type == GR_WITH_ALPHA)
+ png_read_row(png_ptr, p_dst, NULL);
+ else {
+ png_read_row(png_ptr, p_row, NULL);
+ transform_rgb_to_draw(p_row, p_dst, channels, width);
+ }
+ }
+
+ if (img_type == GR_WITHOUT_ALPHA)
+ free(p_row);
+
+ *pSurface = surface;
+exit:
+ if (png_get_io_ptr(png_ptr))
+ fclose((FILE *)png_get_io_ptr(png_ptr));
+
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+
+ return result;
+}
+
+#if 0 /* Currently unneeded */
+static int matches_locale(const char *loc, const char *locale)
+{
+ int i;
+
+ if (locale == NULL)
+ return 0;
+
+ if (!strcmp(loc, locale))
+ return 1;
+
+ /* if loc does *not* have an underscore, and it matches the start
+ * of locale, and the next character in locale *is* an underscore,
+ * that's a match. For instance, loc == "en" matches locale ==
+ * "en_US". */
+
+ for (i = 0; loc[i] != 0 && loc[i] != '_'; ++i)
+ ;
+
+ if (loc[i] == '_')
+ return 0;
+
+ return (!strncmp(locale, loc, i) && locale[i] == '_');
+}
+
+int res_create_localized_alpha_surface(const char *name, const char *locale,
+ gr_surface *pSurface)
+{
+ gr_surface surface = NULL;
+ int result = 0;
+ png_structp png_ptr = NULL;
+ png_infop info_ptr = NULL;
+ png_uint_32 width, height;
+ png_byte channels;
+ unsigned char *row;
+ png_uint_32 y;
+
+ *pSurface = NULL;
+
+ if (locale == NULL) {
+ surface = malloc_surface(0);
+ surface->width = 0;
+ surface->height = 0;
+ surface->row_bytes = 0;
+ surface->pixel_bytes = 1;
+ goto exit;
+ }
+
+ result = open_png(name, &png_ptr, &info_ptr, &width, &height,
+ &channels);
+ if (result < 0) {
+ printf("Can't load image \"%s\": %d.\n", name, result);
+ return result;
+ }
+
+ if (channels != 1) {
+ result = -7;
+ goto exit;
+ }
+
+ row = malloc(width);
+ for (y = 0; y < height; ++y) {
+ int w, h;
+ char *loc;
+
+ png_read_row(png_ptr, row, NULL);
+ w = (row[1] << 8) | row[0];
+ h = (row[3] << 8) | row[2];
+ loc = (char *)row + 5;
+
+ if (y + 1 + h >= height || matches_locale(loc, locale)) {
+ int i;
+
+ printf(" %20s: %s (%d x %d @ %d)\n", name, loc, w, h,
+ (int)y);
+
+ surface = malloc_surface(w * h);
+ if (surface == NULL) {
+ result = -8;
+ goto exit;
+ }
+
+ surface->width = w;
+ surface->height = h;
+ surface->row_bytes = w;
+ surface->pixel_bytes = 1;
+
+ for (i = 0; i < h; i++, y++) {
+ png_read_row(png_ptr, row, NULL);
+ memcpy(surface->data + i * w, row, w);
+ }
+
+ *pSurface = (gr_surface)surface;
+ break;
+ } else {
+ int i;
+
+ for (i = 0; i < h; i++, y++)
+ png_read_row(png_ptr, row, NULL);
+ }
+ }
+
+exit:
+ if (png_get_io_ptr(png_ptr))
+ fclose((FILE *)png_get_io_ptr(png_ptr));
+
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ if (result < 0 && surface != NULL)
+ free(surface);
+
+ return result;
+}
+#endif /* 0 Currently unneeded */
+
+void res_free_surface(gr_surface surface)
+{
+ free(surface);
+}
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "graphics.h"
+#include "rui-description.h"
+
+void rui_description_draw(rui_description *d)
+{
+ if (!d)
+ return;
+
+ gr_set_color(d->style->c_title);
+ gr_text(d->pos_x, d->pos_y, d->title, GR_FONT_BOLD);
+ gr_set_color(d->style->c_text);
+ gr_text(d->pos_x, d->pos_y + gr_get_font_cheight(), d->text,
+ GR_FONT_BOLD);
+}
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "graphics.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ color c_title;
+ color c_text;
+} rui_description_style;
+
+typedef struct {
+ int pos_x;
+ int pos_y;
+ rui_description_style *style;
+ const char *title;
+ const char *text;
+} rui_description;
+
+void rui_description_draw(rui_description *d);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "graphics.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ RUI_IMAGE_NONE = -1
+} rui_image_id;
+
+typedef enum {
+ RUI_ANIMATION_NONE = -1
+} rui_animation_id;
+
+typedef struct {
+ const char *fname;
+ color c_bg;
+ gr_align_horizontal align_hor;
+ gr_align_vertical align_ver;
+ int offset_x,
+ offset_y;
+ gr_img_type img_type;
+ gr_surface surface;
+} rui_image;
+
+typedef struct {
+ const char *fname;
+ color c_bg;
+ gr_align_horizontal align_hor;
+ gr_align_vertical align_ver;
+ int frames_num,
+ current_frame;
+ int offset_x,
+ offset_y;
+ gr_img_type img_type;
+ gr_surface *surfaces;
+} rui_animation;
+
+void rui_images_init(rui_image *images, int images_num,
+ rui_animation *animations, int animations_num);
+void rui_images_exit(void);
+void rui_images_draw(void);
+void rui_animations_draw(void);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "rui.h"
+#include "common.h"
+#include "graphics.h"
+#include "rui-image.h"
+
+static rui_image *rui_images = NULL;
+static rui_animation *rui_animations = NULL;
+static int rui_images_num = 0, rui_animations_num = 0;
+
+void rui_images_draw(void)
+{
+ size_t i = 0;
+ rui_screen *cs;
+ rui_image_id img_id;
+
+ cs = get_current_screen();
+ if (!cs->images)
+ return;
+
+ while ((img_id = cs->images[i]) != RUI_IMAGE_NONE) {
+ rui_image *img = &rui_images[img_id];
+
+ if (!img->surface) {
+ i++;
+ continue;
+ }
+
+ if (img->img_type == GR_WITH_ALPHA) {
+ gr_set_color(img->c_bg);
+ gr_blend_image_aligned(img->surface, img->align_hor,
+ img->align_ver, img->offset_x,
+ img->offset_y);
+ } else
+ gr_blit_image_aligned(img->surface, img->align_hor,
+ img->align_ver, img->offset_x,
+ img->offset_y);
+
+ i++;
+ }
+}
+
+void rui_animations_draw(void)
+{
+ int i = 0;
+ rui_screen *cs;
+ rui_animation_id anim_id;
+
+ cs = get_current_screen();
+ if (!cs->animations)
+ return;
+
+ while ((anim_id = cs->animations[i]) != RUI_ANIMATION_NONE) {
+ rui_animation *anim = &rui_animations[anim_id];
+
+ if (!anim->surfaces) {
+ i++;
+ continue;
+ }
+
+ if (anim->img_type == GR_WITH_ALPHA) {
+ gr_set_color(anim->c_bg);
+ gr_blend_image_aligned(anim->surfaces[anim->current_frame],
+ anim->align_hor,
+ anim->align_ver,
+ anim->offset_x,
+ anim->offset_y);
+ } else
+ gr_blit_image_aligned(anim->surfaces[anim->current_frame],
+ anim->align_hor,
+ anim->align_ver,
+ anim->offset_x,
+ anim->offset_y);
+
+ i++;
+ if (++anim->current_frame >= anim->frames_num)
+ anim->current_frame = 0;
+ }
+}
+
+void rui_images_init(rui_image *images,
+ int images_num,
+ rui_animation *animations,
+ int animations_num)
+{
+ int i;
+
+ rui_images = images;
+ rui_images_num = images_num;
+ rui_animations = animations;
+ rui_animations_num = animations_num;
+
+ for (i = 0; i < rui_images_num; i++)
+ if (res_create_image_surface(rui_images[i].fname,
+ &rui_images[i].surface,
+ rui_images[i].img_type) < 0)
+ rui_images[i].surface = NULL;
+
+ for (i = 0; i < rui_animations_num; i++)
+ if (res_create_anim_image_surfaces(rui_animations[i].fname,
+ &rui_animations[i].frames_num,
+ &rui_animations[i].surfaces,
+ rui_animations[i].img_type) < 0)
+ rui_animations[i].surfaces = NULL;
+}
+
+void rui_images_exit(void)
+{
+ int i;
+
+ for (i = 0; i < rui_images_num; i++)
+ if (rui_images[i].surface) {
+ res_free_surface(rui_images[i].surface);
+ rui_images[i].surface = NULL;
+ }
+
+ rui_images = NULL;
+ rui_images_num = 0;
+
+ for (i = 0; i < rui_animations_num; i++)
+ if (rui_animations[i].surfaces) {
+ int j;
+
+ for (j = 0; j < rui_animations[i].frames_num; j++)
+ res_free_surface(rui_animations[i].surfaces[j]);
+
+ free(rui_animations[i].surfaces);
+ rui_animations[i].surfaces = NULL;
+ }
+
+ rui_animations = NULL;
+ rui_animations_num = 0;
+}
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+
+#include "rui.h"
+#include "graphics.h"
+#include "rui-menu.h"
+
+static void rui_menu_draw_item(int i, rui_menu *m)
+{
+ gr_set_color((i == m->item_selected) ? m->style->c_bg_selected :
+ m->style->c_bg_unselected);
+ gr_draw_rectangle(m->pos_x,
+ m->pos_y + i * (m->style->item_height +
+ m->style->item_spacing),
+ gr_fb_width() - m->pos_x, m->style->item_height);
+
+ gr_set_color((i == m->item_selected) ? m->style->c_text_selected :
+ m->style->c_text_unselected);
+ gr_text(m->style->text_pos_x,
+ m->pos_y +
+ i * (m->style->item_height + m->style->item_spacing) +
+ (m->style->item_height - gr_get_font_cheight()) / 2,
+ m->items[i],
+ (i == m->item_selected) ? GR_FONT_BOLD : GR_FONT_REGULAR);
+}
+
+void rui_menu_draw(rui_menu *menu)
+{
+ int i;
+
+ if (!menu)
+ return;
+
+ for (i = 0; i < menu->items_num; i++)
+ rui_menu_draw_item(i, menu);
+}
+
+int rui_menu_cursor_up(rui_menu *menu)
+{
+ if (!menu)
+ return 0; /* Don't need to repaint */
+
+ if (--menu->item_selected < 0)
+ menu->item_selected = menu->items_num - 1;
+
+ return 1; /* Need repaint */
+}
+
+int rui_menu_cursor_down(rui_menu *menu)
+{
+ if (!menu)
+ return 0; /* Don't need to repaint */
+
+ if (++menu->item_selected >= menu->items_num)
+ menu->item_selected = 0;
+
+ return 1; /* Need repaint */
+}
+
+int rui_menu_action_run(rui_menu *menu)
+{
+ int item_selected;
+ int ret;
+
+ if (!menu || !menu->actions)
+ return 0; /* Don't need to repaint */
+
+ item_selected = menu->item_selected;
+ rui_screen_switch(menu->actions[item_selected].screen_switch_to);
+ if (menu->actions[item_selected].action_handler) {
+ ret = system(menu->actions[item_selected].action_handler);
+ if (ret < 0)
+ return ret;
+
+ if (menu->actions[item_selected].exit_after_action)
+ exit(0);
+ }
+
+ return 1; /* Repaint unconditionally. Just in case. */
+}
+
+void rui_menu_init(rui_menu *menu)
+{
+ if (!menu)
+ return;
+
+ if (menu->item_default != RUI_MENU_ITEM_DO_NOT_CHANGE)
+ menu->item_selected = menu->item_default;
+}
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "graphics.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ int item_height,
+ item_spacing,
+ text_pos_x;
+ color c_bg_selected,
+ c_bg_unselected,
+ c_text_selected,
+ c_text_unselected;
+} rui_menu_style;
+
+typedef enum {
+ RUI_MENU_ITEM_DO_NOT_CHANGE = -1
+} rui_menu_item_id;
+
+struct rui_menu_t;
+
+typedef struct {
+ int screen_switch_to;
+ const char *action_handler;
+ int exit_after_action;
+} rui_menu_action;
+
+typedef struct rui_menu_t {
+ rui_menu_style *style;
+ int pos_x,
+ pos_y,
+ items_num,
+ item_selected,
+ item_default;
+ const char **items;
+ rui_menu_action *actions;
+} rui_menu;
+
+void rui_menu_draw(rui_menu *menu);
+int rui_menu_cursor_up(rui_menu *menu);
+int rui_menu_cursor_down(rui_menu *menu);
+int rui_menu_action_run(rui_menu *menu);
+void rui_menu_init(rui_menu *menu);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rui.h"
+#include "graphics.h"
+#include "rui-progress-bar.h"
+
+void rui_progress_bar_draw(rui_progress_bar *b)
+{
+ int width, progress_width;
+
+ if (!b)
+ return;
+
+ gr_set_color(b->style->c_border);
+ width = gr_fb_width() - 2 * b->pos_x;
+ /* Draw progress bar symmetrically to center. */
+ gr_draw_rectangle(b->pos_x, b->pos_y, width, b->height);
+ progress_width = b->progress *
+ (width - 2 * b->style->border_width) / 100;
+
+ if (b->progress != 0) { /* Draw bar. */
+ gr_set_color(b->style->c_bar);
+ gr_draw_rectangle(b->pos_x + b->style->border_width,
+ b->pos_y + b->style->border_width,
+ progress_width,
+ b->height - 2 * b->style->border_width);
+ }
+
+ if (b->progress != 100) { /* Draw background. */
+ gr_set_color(b->style->c_background);
+ gr_draw_rectangle(b->pos_x + b->style->border_width +
+ progress_width,
+ b->pos_y + b->style->border_width,
+ width - 2 * b->style->border_width -
+ progress_width,
+ b->height - 2 * b->style->border_width);
+ }
+}
+
+int rui_progress_bar_get_progress(rui_progress_bar *b)
+{
+ return b->progress;
+}
+
+/* Set progress value for progress bar on the current screen. */
+void rui_progress_bar_set_progress(rui_progress_bar *b, int progress)
+{
+ if (!b || progress < 0 || progress > 100)
+ return;
+
+ b->progress = progress;
+}
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "graphics.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ color c_background,
+ c_border,
+ c_bar;
+ int border_width;
+} rui_progress_bar_style;
+
+typedef struct {
+ int pos_x,
+ pos_y,
+ height,
+ progress; /* 0 - 100 */
+ rui_progress_bar_style *style;
+} rui_progress_bar;
+
+void rui_progress_bar_draw(rui_progress_bar *b);
+int rui_progress_bar_get_progress(rui_progress_bar *b);
+void rui_progress_bar_set_progress(rui_progress_bar *b, int progress);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "graphics.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ color c_ruler;
+} rui_ruler_style;
+
+typedef struct {
+ int pos_x,
+ pos_y,
+ height;
+ rui_ruler_style *style;
+} rui_ruler;
+
+void rui_rulers_draw(rui_ruler *rulers);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "graphics.h"
+#include "rui-ruler.h"
+
+void rui_rulers_draw(rui_ruler *rulers)
+{
+ rui_ruler *r = rulers;
+
+ while (r) {
+ if (!r->style)
+ break;
+
+ gr_set_color(r->style->c_ruler);
+ /* Draw ruler symmetrically to center. */
+ gr_draw_rectangle(r->pos_x, r->pos_y,
+ gr_fb_width() - 2 * r->pos_x, r->height);
+ r++;
+ }
+}
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+#include "rui.h"
+#include "common.h"
+#include "rui-menu.h"
+#include "graphics.h"
+#include "rui-image.h"
+#include "rui-ruler.h"
+#include "input-events.h"
+#include "rui-description.h"
+
+static rui_screen *rui_screens = NULL;
+static int rui_screens_num = 0, rui_current_screen = 0;
+
+rui_screen * get_current_screen(void)
+{
+ return &rui_screens[rui_current_screen];
+}
+
+int get_current_screen_id(void)
+{
+ return rui_current_screen;
+}
+
+void rui_draw(void)
+{
+ rui_screen *cs;
+
+ cs = get_current_screen();
+ if (cs->style)
+ gr_set_color(cs->style->c_background);
+ gr_clear();
+ rui_images_draw();
+ rui_animations_draw();
+
+ if (cs->rulers)
+ rui_rulers_draw(cs->rulers);
+
+ if (cs->menu)
+ rui_menu_draw(cs->menu);
+
+ if (cs->description)
+ rui_description_draw(cs->description);
+
+ if (cs->progress_bar)
+ rui_progress_bar_draw(cs->progress_bar);
+
+ if (cs->draw)
+ cs->draw();
+
+ gr_flip();
+}
+
+/* Returns need_repaint */
+bool rui_screen_switch(int screen)
+{
+ if (screen == RUI_SCREEN_CURRENT || screen == get_current_screen_id())
+ return false; /* Don't need to repaint */
+
+ if (screen == RUI_SCREEN_BACK) {
+ rui_screen *cs;
+
+ cs = get_current_screen();
+ return rui_screen_switch(cs->screen_back);
+ }
+
+ rui_current_screen = screen;
+ if (rui_screens[screen].menu)
+ rui_menu_init(rui_screens[screen].menu);
+
+ if (rui_screens[screen].progress_bar)
+ rui_progress_bar_set_progress(
+ rui_screens[screen].progress_bar, 0);
+
+ if (rui_screens[screen].on_enter)
+ rui_screens[screen].on_enter();
+
+ return true; /* Need to repaint */
+}
+
+bool rui_init(rui_screen *screens, int screens_num, int current_screen,
+ rui_image *images, int images_num,
+ rui_animation *animations, int animations_num)
+{
+ if (!gr_init())
+ return false;
+
+ rui_screens = screens;
+ rui_screens_num = screens_num;
+ rui_current_screen = current_screen;
+ rui_images_init(images, images_num, animations, animations_num);
+ return true;
+}
+
+void rui_exit(void)
+{
+ rui_images_exit();
+ gr_exit();
+}
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+
+#include "graphics.h"
+#include "rui-menu.h"
+#include "rui-image.h"
+#include "rui-ruler.h"
+#include "rui-description.h"
+#include "rui-progress-bar.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*rui_screen_on_enter)(void);
+typedef void (*rui_screen_draw)(void);
+
+typedef struct {
+ color c_background;
+} rui_screen_style;
+
+typedef enum {
+ RUI_SCREEN_BACK = -2,
+ RUI_SCREEN_CURRENT = -1
+} rui_screen_id;
+
+typedef struct {
+ rui_screen_style *style;
+ rui_menu *menu;
+ rui_description *description;
+ rui_ruler *rulers;
+ rui_progress_bar *progress_bar;
+ int *images;
+ rui_animation_id *animations;
+ int rulers_num;
+ rui_screen_on_enter on_enter;
+ rui_screen_draw draw;
+ int screen_back;
+ int allow_force_reboot;
+} rui_screen;
+
+bool rui_init(rui_screen *screens, int screens_num, int current_screen,
+ rui_image *images, int images_num,
+ rui_animation *animations, int animations_num);
+void rui_exit(void);
+void rui_draw(void);
+bool rui_screen_switch(int screen); /* Returns need_repaint */
+rui_screen *get_current_screen(void);
+int get_current_screen_id(void);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil -*-
+ *
+ * system-recovery
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Based on tdm-if.c from tota-ua.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/poll.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "tdm-if.h"
+
+#define LOGD(format, ...) printf("[TDM-IF] " format "\n", ##__VA_ARGS__)
+
+#define C(b, m) (((b) >> (m)) & 0xFF)
+#define B(c, s) ((((unsigned int)(c)) & 0xff) << (s))
+#define FOURCC(a, b, c, d) (B(d, 24) | B(c, 16) | B(b, 8) | B(a, 0))
+#define FOURCC_STR(id) C(id, 0), C(id, 8), C(id, 16), C(id, 24)
+#define FOURCC_ID(str) FOURCC(((char*)str)[0], ((char*)str)[1], ((char*)str)[2], ((char*)str)[3])
+
+static tdm_if_disp s_st_disp;
+
+static void tdm_if_display_commit_handler_cb(tdm_output *output, unsigned int sequence,
+ unsigned int tv_sec, unsigned int tv_usec,
+ void *user_data)
+{
+ LOGD("commit_handle_cb!!");
+
+ return ;
+}
+
+int tdm_if_display_init(void)
+{
+ const tdm_output_mode *output_modes, *preferred_mode;
+ tdm_info_layer layer_info;
+ tdm_layer_capability layer_caps;
+ tdm_output_conn_status conn_status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
+ tdm_output_type output_type = TDM_OUTPUT_TYPE_Unknown;
+ tdm_output *output = NULL;
+ int buf_cnt;
+ tdm_error err = TDM_ERROR_NONE;
+ tdm_if_disp *st_disp = &s_st_disp;
+ int i, j;
+ int layer_count = 0;
+ int output_count = 0;
+
+ LOGD("START");
+
+ st_disp->disp = tdm_display_init(&err);
+ if (!st_disp->disp) {
+ LOGD("failed to init tdm_display. error num = %d", err);
+ goto exit;
+ }
+
+ err = tdm_display_get_fd(st_disp->disp, &st_disp->tdm_fd);
+ if (err != TDM_ERROR_NONE) {
+ LOGD("failed to get tdm fd. error num = %d", err);
+ goto exit;
+ }
+
+ st_disp->drm_fd = tdm_helper_get_fd("TDM_DRM_MASTER_FD");
+ if (st_disp->drm_fd == -1) {
+ LOGD("failed to get tdm fd. error num = %d", err);
+ goto exit;
+ }
+
+ err = tdm_display_get_output_count(st_disp->disp, &output_count);
+ if (err != TDM_ERROR_NONE) {
+ LOGD("failed to get output count. error num = %d", err);
+ goto exit;
+ }
+
+ if (output_count < 1) {
+ LOGD("insufficient number of outputs");
+ goto exit;
+ }
+
+ for (i = 0; i < output_count; i++) {
+ output = tdm_display_get_output(st_disp->disp, i, &err);
+ if (err != TDM_ERROR_NONE) {
+ LOGD("failed to get outout. error num = %d", err);
+ goto exit;
+ }
+
+ err = tdm_output_get_output_type(output, &output_type);
+ if (err != TDM_ERROR_NONE) {
+ LOGD("failed to get output type. error num = %d", err);
+ goto exit;
+ }
+
+ err = tdm_output_get_conn_status(output, &conn_status);
+ if (err != TDM_ERROR_NONE) {
+ LOGD("failed to get output connection status. error num = %d", err);
+ goto exit;
+ }
+
+ LOGD("output_type=%d conn_status=%d", output_type, conn_status);
+ if ((output_type == TDM_OUTPUT_TYPE_LVDS) ||
+ (output_type == TDM_OUTPUT_TYPE_DSI)) {
+ int cnt = 0;
+ err = tdm_output_get_available_modes(output, &output_modes, &cnt);
+ if (err != TDM_ERROR_NONE) {
+ LOGD("failed to get output available modes. error num = %d", err);
+ goto exit;
+ }
+ LOGD("%d output modes available", cnt);
+
+ preferred_mode = output_modes;
+ for (j = 0; j < cnt; j++) {
+ if (output_modes[i].type & TDM_OUTPUT_MODE_TYPE_PREFERRED) {
+ preferred_mode = &output_modes[i];
+ break;
+ }
+ }
+
+ /* GET MODE INFO */
+ st_disp->output = output;
+ st_disp->width = preferred_mode->hdisplay;
+ st_disp->height = preferred_mode->vdisplay;
+
+ err = tdm_output_set_mode(st_disp->output, preferred_mode);
+ if (err != TDM_ERROR_NONE) {
+ LOGD("unable to set mode: \"%s\"", preferred_mode->name);
+ goto exit;
+ }
+
+ /* informational */
+ unsigned int width_mm = 0;
+ unsigned int height_mm = 0;
+ err = tdm_output_get_physical_size(output, &width_mm, &height_mm);
+ LOGD("TDM_OUTPUT_MODE:name[%s] mode:wh[%d %d] mm[%d %d]",
+ preferred_mode->name, st_disp->width, st_disp->height, width_mm, height_mm);
+
+ break;
+ }
+ }
+
+ /* SET LAYER */
+ err = tdm_output_get_layer_count(st_disp->output, &layer_count);
+ if (err != TDM_ERROR_NONE) {
+ LOGD("failed to get number of layers");
+ goto exit;
+ }
+ if (layer_count < 1) {
+ LOGD("insufficient number of layers: %d", layer_count);
+ goto exit;
+ }
+
+ for (i = 0; i < layer_count; i++) {
+ st_disp->layer = tdm_output_get_layer(st_disp->output, i, &err);
+ if (err != TDM_ERROR_NONE) {
+ LOGD("failed to get layer: %d", i);
+ goto exit;
+ }
+
+ err = tdm_layer_get_capabilities(st_disp->layer, &layer_caps);
+ if (err != TDM_ERROR_NONE) {
+ LOGD("failed to get layer capabilities: %d", i);
+ goto exit;
+ }
+
+ if ((layer_caps & TDM_LAYER_CAPABILITY_PRIMARY) &&
+ (layer_caps & TDM_LAYER_CAPABILITY_GRAPHIC))
+ break;
+ }
+
+ layer_info.src_config.size.h = st_disp->width;
+ layer_info.src_config.size.v = st_disp->height;
+ layer_info.src_config.pos.x = 0;
+ layer_info.src_config.pos.y = 0;
+ layer_info.src_config.pos.w = st_disp->width;
+ layer_info.src_config.pos.h = st_disp->height;
+ layer_info.src_config.format = TBM_FORMAT_ARGB8888;
+ layer_info.dst_pos.x = 0;
+ layer_info.dst_pos.y = 0;
+ layer_info.dst_pos.w = st_disp->width;
+ layer_info.dst_pos.h = st_disp->height;
+ layer_info.transform = TDM_TRANSFORM_NORMAL;
+
+ err = tdm_layer_set_info(st_disp->layer, &layer_info);
+ if (err != TDM_ERROR_NONE) {
+ LOGD("failed to get output layer. error num = %d", err);
+ goto exit;
+ }
+
+ for (buf_cnt = 0; buf_cnt < MAX_BUF; buf_cnt++) {
+ tbm_surface_error_e e;
+ tbm_surface_info_s si;
+
+ st_disp->surf[buf_cnt] = tbm_surface_internal_create_with_flags(st_disp->width,
+ st_disp->height,
+ TBM_FORMAT_ARGB8888,
+ TBM_BO_SCANOUT);
+ e = get_last_result();
+ if (e != TBM_SURFACE_ERROR_NONE ||
+ !st_disp->surf[buf_cnt]){
+ LOGD("failed to create tbm_surface!");
+ goto exit;
+ }
+
+ e = tbm_surface_get_info(st_disp->surf[buf_cnt], &si);
+ if (e != TBM_SURFACE_ERROR_NONE) {
+ LOGD("failed to get info for tbm_surface!");
+ goto exit;
+ }
+
+ LOGD("surface created: %dx%d %c%c%c%c bpp:%d size:%d planes:%d stride:%d",
+ si.width, si.height,
+ FOURCC_STR(si.format),
+ si.bpp, si.size, si.num_planes,
+ si.planes[0].stride);
+
+ if (si.num_planes != 1) {
+ LOGD("unsupported number of planes: %d", si.num_planes);
+ goto exit;
+ }
+ st_disp->buffer_size = si.planes[0].size;
+ st_disp->stride = si.planes[0].stride;
+ }
+
+
+ st_disp->current_buf_id = 0;
+
+ for (i = 0; i < MAX_BUF; i++) {
+ tdm_if_buffer_update(NULL);
+ tdm_if_display_update();
+ }
+
+ LOGD("DONE");
+ return 0;
+exit:
+ tdm_if_display_deinit();
+ return -1;
+}
+
+void tdm_if_display_deinit(void)
+{
+ int buf_cnt = 0;
+ tdm_if_disp *st_disp = &s_st_disp;
+
+ tdm_if_lcd_off();
+
+ if (st_disp->disp != NULL) {
+ /* RELEASE RESOURCE */
+ for (buf_cnt = 0; buf_cnt < MAX_BUF; buf_cnt++) {
+ if (st_disp->surf[buf_cnt] != NULL)
+ tbm_surface_destroy(st_disp->surf[buf_cnt]);
+ }
+
+ tdm_display_deinit(st_disp->disp);
+ st_disp->disp = NULL;
+ }
+}
+
+int tdm_if_display_width(void)
+{
+ tdm_if_disp *st_disp = &s_st_disp;
+ return st_disp->width;
+}
+
+int tdm_if_display_height(void)
+{
+ tdm_if_disp *st_disp = &s_st_disp;
+ return st_disp->height;
+}
+
+int tdm_if_display_bufsize(void)
+{
+ tdm_if_disp *st_disp = &s_st_disp;
+ return st_disp->buffer_size;
+}
+
+int tdm_if_display_stride(void)
+{
+ tdm_if_disp *st_disp = &s_st_disp;
+ return st_disp->stride;
+}
+
+void tdm_if_buffer_update(unsigned char *buffer)
+{
+ tdm_if_disp *st_disp = &s_st_disp;
+ int buf_cnt = st_disp->current_buf_id;
+ tbm_surface_info_s tbm_surface_info;
+ tbm_surface_error_e err;
+ uint32_t *surface;
+
+ err = tbm_surface_map(st_disp->surf[buf_cnt], TBM_SURF_OPTION_WRITE, &tbm_surface_info);
+ if (err != TBM_SURFACE_ERROR_NONE) {
+ LOGD("tbm_surface_map failed!");
+ return;
+ }
+
+ surface = (uint32_t*)tbm_surface_info.planes[0].ptr;
+
+ if (buffer == NULL)
+ memset(surface, 0, st_disp->buffer_size);
+ else
+ memcpy(surface, buffer, st_disp->buffer_size);
+
+ tbm_surface_unmap(st_disp->surf[buf_cnt]);
+}
+
+void tdm_if_display_update(void)
+{
+ /* DISPLAY UPDATE */
+ int buf_cnt = 0;
+ tdm_if_disp *st_disp = &s_st_disp;
+
+ buf_cnt = st_disp->current_buf_id;
+ st_disp->current_buf_id = (st_disp->current_buf_id + 1)%MAX_BUF;
+
+ tdm_layer_set_buffer(st_disp->layer, st_disp->surf[buf_cnt]);
+
+ // TODO: sync or async??
+ tdm_output_commit(st_disp->output, 1, tdm_if_display_commit_handler_cb, st_disp);
+}
+
+void tdm_if_lcd_on(void)
+{
+ tdm_if_disp *st_disp = &s_st_disp;
+
+ LOGD("DPMS ON!");
+ tdm_output_set_dpms(st_disp->output, TDM_OUTPUT_DPMS_ON);
+}
+
+void tdm_if_lcd_off(void)
+{
+ tdm_if_disp *st_disp = &s_st_disp;
+
+ LOGD("DPMS OFF!");
+ tdm_output_set_dpms(st_disp->output, TDM_OUTPUT_DPMS_OFF);
+}
--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil -*-
+ *
+ * system-recovery
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Based on tdm-if.h from tota-ua.
+ */
+
+#ifndef __TDM_IF_H__
+#define __TDM_IF_H__
+
+#include <tbm_bufmgr.h>
+#include <tbm_surface.h>
+#include <tbm_surface_internal.h>
+#include <tdm.h>
+#include <tdm_helper.h>
+
+#define MAX_BUF 2
+#define RGB32_BPP 32
+#define RGB32_PITCH 4
+
+typedef struct _tdm_if_disp {
+ tdm_display *disp;
+ tdm_output *output;
+ tdm_layer *layer;
+ int tdm_fd;
+ int drm_fd;
+ tbm_surface_h surf[MAX_BUF];
+ int buffer_size;
+ int width;
+ int height;
+ int stride;
+ int current_buf_id;
+} tdm_if_disp;
+
+typedef enum {
+ FRONT_BUFFER = 0,
+ BACK_BUFFER
+} BUFFER_TYPE;
+
+extern tdm_if_disp s_disp;
+
+int tdm_if_display_init(void);
+void tdm_if_display_deinit(void);
+void tdm_if_display_update(void);
+int tdm_if_display_width(void);
+int tdm_if_display_height(void);
+int tdm_if_display_bufsize(void);
+int tdm_if_display_stride(void);
+
+void tdm_if_buffer_update(unsigned char *buffer);
+
+void tdm_if_lcd_on(void);
+void tdm_if_lcd_off(void);
+
+#endif /* __TDM_IF_H__ */
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * libsystem
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <limits.h>
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "log.h"
+
+#define FILEBUF 1024
+
+static inline void __cleanup_free_func(void *p)
+{
+ free(*(void**) p);
+}
+
+static inline bool isempty(const char *p)
+{
+ return !p || !p[0];
+}
+
+#define _cleanup_(x) __attribute__((cleanup(x)))
+
+#define _cleanup_free_ _cleanup_(__cleanup_free_func)
+
+#define new(t, n) ((t*) malloc(sizeof(t) * (n)))
+
+#define FOREACH_WORD_SEPARATOR(word, length, s, separator, state) \
+ for ((state) = NULL, (word) = split((s), &(length), (separator), &(state)); (word); (word) = split((s), &(length), (separator), &(state)))
+
+#define strncaseeq(a, b, n) (strncasecmp((a), (b), (n)) == 0)
+
+static FILE *log_f[LOG_TYPE_MAX];
+static int stdout_bak = -1;
+static int stderr_bak = -1;
+
+static int log_level = LOG_DEBUG;
+
+static const char const *log_priority_name[] = {
+ [LOG_ALERT] = "alert",
+ [LOG_CRIT] = "crit",
+ [LOG_DEBUG] = "debug",
+ [LOG_EMERG] = "emerg",
+ [LOG_ERR] = "err",
+ [LOG_INFO] = "info",
+ [LOG_NOTICE] = "notice",
+ [LOG_WARNING] = "warning"
+};
+
+void set_log_level(int level)
+{
+ log_level = level;
+}
+
+int get_log_level(void)
+{
+ return log_level;
+}
+
+static bool __quote_complete(char *str, size_t l, char q)
+{
+ char *s, *s2;
+
+ assert(str);
+
+ if (!l)
+ return true;
+
+ s = strchr(str, q);
+ if (!s || (s - str) > l)
+ return true;
+
+ s = strchr(s + 1, q);
+ if (!s || (s - str) > l)
+ return false;
+
+ s2 = strchr(s + 1, q);
+ if (!s2 || (s2 - str) > l)
+ return true;
+
+ return __quote_complete(s + 1, l - (s + 1 - str), q);
+}
+
+#define QUOTES "\"\'"
+static bool quote_complete(char *str, size_t l)
+{
+ char quotes[] = QUOTES;
+ int i;
+
+ assert(str);
+
+ if (!l)
+ return true;
+
+ for (i = 0; quotes[i]; i++) {
+ if (!__quote_complete(str, l, quotes[i]))
+ return false;
+ }
+
+ return true;
+}
+
+static char *split(const char *c, size_t *l, const char *separator, char **state)
+{
+ bool separator_include_quotes;
+ char *current;
+ size_t s;
+
+ assert(c);
+ assert(l);
+ assert(separator);
+ assert(state);
+
+ current = *state ? *state : (char *) c;
+ if (!*current || *c == 0)
+ return NULL;
+
+ *l = 0;
+ separator_include_quotes = !!strspn(separator, QUOTES);
+ current += strspn(current, separator);
+
+ while ((s = strcspn(current + *l, separator))) {
+ *l += s;
+ if (separator_include_quotes ||
+ quote_complete(current, *l))
+ break;
+ (*l)++;
+ }
+
+ *state = current + *l;
+
+ return (char *) current;
+}
+
+static int stdpath_dup_and_backup(FILE *f)
+{
+ int r, fd;
+
+ stdout_bak = dup(STDOUT_FILENO);
+ stderr_bak = dup(STDERR_FILENO);
+
+ fd = fileno(f);
+ r = dup2(fd, STDOUT_FILENO);
+ if (r < 0)
+ return -errno;
+
+ r = dup2(fd, STDERR_FILENO);
+ if (r < 0)
+ return -errno;
+
+ return 0;
+}
+
+static int stdpath_restore(void)
+{
+ int r;
+
+ if (stdout_bak >= 0) {
+ r = dup2(stdout_bak, STDOUT_FILENO);
+ if (r < 0)
+ return -errno;
+
+ close(stdout_bak);
+ stdout_bak = -1;
+ }
+
+ if (stderr_bak >= 0) {
+ r = dup2(stderr_bak, STDERR_FILENO);
+ if (r < 0)
+ return -errno;
+
+ close(stderr_bak);
+ stderr_bak = -1;
+ }
+
+ return 0;
+}
+
+int log_open(enum log_mask log_set, const char *path)
+{
+ int r;
+
+ if (log_set & LOG_MASK_FILE) {
+ assert(path);
+
+ log_f[LOG_TYPE_FILE] = fopen(path, "w+");
+ if (!log_f[LOG_TYPE_FILE])
+ return -errno;
+
+ /* If standard output/error were not set, redirect
+ * standard output/error to log file */
+ if (!(log_set & LOG_MASK_STANDARD)) {
+ r = stdpath_dup_and_backup(log_f[LOG_TYPE_FILE]);
+ if (r < 0)
+ return r;
+ }
+ }
+
+ if (log_set & LOG_MASK_KMSG) {
+ log_f[LOG_TYPE_KMSG] = fopen("/dev/kmsg", "we");
+ if (!log_f[LOG_TYPE_KMSG])
+ return -errno;
+
+ /* If standard output/error or log file were not set,
+ * redirect standard output/error to kmsg */
+ if (!(log_set & LOG_MASK_STANDARD) &&
+ !(log_set & LOG_MASK_FILE)) {
+ r = stdpath_dup_and_backup(log_f[LOG_TYPE_KMSG]);
+ if (r < 0)
+ return r;
+ }
+ }
+
+ return 0;
+}
+
+int log_close(void)
+{
+ enum log_type type;
+
+ for (type = 0; type < LOG_TYPE_MAX; type++) {
+ if (type == LOG_TYPE_STANDARD || !log_f[type])
+ continue;
+
+ fclose(log_f[type]);
+ log_f[type] = NULL;
+ }
+
+ return stdpath_restore();
+}
+
+static int _log_write(
+ int level,
+ const char *file,
+ int line,
+ const char *func,
+ const char *format,
+ va_list ap)
+{
+ char buff[LINE_MAX];
+ enum log_type type;
+
+ vsnprintf(buff, LINE_MAX, format, ap);
+
+ for (type = 0; type < LOG_TYPE_MAX; type++) {
+ if (type != LOG_TYPE_STANDARD && !log_f[type])
+ continue;
+
+ switch (type) {
+ case LOG_TYPE_STANDARD:
+ fprintf(level <= LOG_ERR ? stderr : stdout,
+ "%s\n", buff);
+ break;
+ case LOG_TYPE_FILE:
+ fprintf(log_f[LOG_TYPE_FILE],
+ "%-8s: %s\n", log_priority_name[level], buff);
+ fflush(log_f[LOG_TYPE_FILE]);
+ break;
+ case LOG_TYPE_KMSG:
+ fprintf(log_f[LOG_TYPE_KMSG],
+ "initrd: %s\n", buff);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int log_write(
+ int level,
+ const char*file,
+ int line,
+ const char *func,
+ const char *format, ...)
+{
+ va_list ap;
+ int r;
+
+ va_start(ap, format);
+ r = _log_write(level, file, line, func, format, ap);
+ va_end(ap);
+
+ return r;
+}
+
+int log_move(const char *to)
+{
+ _cleanup_free_ char *buf = NULL;
+ FILE *w = NULL;
+ size_t len;
+ int r;
+
+ assert(to);
+
+ if (!log_f[LOG_TYPE_FILE])
+ return 0;
+
+ buf = new(char, FILEBUF);
+ if (!buf) {
+ r = -ENOMEM;
+ goto error;
+ }
+
+ w = fopen(to, "a+");
+ if (!w) {
+ r = -errno;
+ goto error;
+ }
+
+ r = fseek(log_f[LOG_TYPE_FILE], 0, SEEK_SET);
+ if (r < 0) {
+ r = -errno;
+ goto error;
+ }
+
+ r = fflush(log_f[LOG_TYPE_FILE]);
+ if (r < 0) {
+ r = -errno;
+ goto error;
+ }
+
+ while ((len = fread(buf, sizeof(char), FILEBUF, log_f[LOG_TYPE_FILE])) > 0) {
+ if (fwrite(buf, sizeof(char), len, w) != len) {
+ r = -errno;
+ goto error;
+ }
+ }
+
+ fclose(log_f[LOG_TYPE_FILE]);
+ log_f[LOG_TYPE_FILE] = w;
+
+ r = stdpath_dup_and_backup(log_f[LOG_TYPE_FILE]);
+ if (r < 0)
+ goto error;
+
+ return 0;
+
+error:
+ if (w)
+ fclose(w);
+
+ log_dbg("Failed to move log: %d\n", errno);
+
+ return r;
+}
+
+enum log_mask parse_log_type(const char *type)
+{
+ char *word, *state;
+ enum log_mask mask = 0;
+ size_t l;
+
+ if (!type)
+ return LOG_MASK_INVALID;
+
+ FOREACH_WORD_SEPARATOR(word, l, type, "+", state) {
+
+ if (strncaseeq(word, "standard", l))
+ mask |= LOG_MASK_STANDARD;
+ else if (strncaseeq(word, "file", l))
+ mask |= LOG_MASK_FILE;
+ else if (strncaseeq(word, "kmsg", l))
+ mask |= LOG_MASK_KMSG;
+ else
+ return LOG_MASK_INVALID;
+ }
+
+ return mask;
+}
+
+int config_parse_log_type(
+ const char *filename,
+ unsigned line,
+ const char *section,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data)
+{
+
+ enum log_mask *mask = data;
+
+ if (isempty(rvalue))
+ return 0;
+
+ *mask = parse_log_type(rvalue);
+
+ return *mask == LOG_MASK_INVALID ? -EINVAL : 0;
+}
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * libsystem
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <sys/syslog.h>
+#include <stdbool.h>
+
+enum log_type {
+ LOG_TYPE_INVALID = -1,
+ LOG_TYPE_STANDARD = 0,
+ LOG_TYPE_FILE,
+ LOG_TYPE_KMSG,
+ LOG_TYPE_MAX
+};
+
+enum log_mask {
+ LOG_MASK_INVALID = -1,
+ LOG_MASK_STANDARD = 1 << LOG_TYPE_STANDARD,
+ LOG_MASK_FILE = 1 << LOG_TYPE_FILE,
+ LOG_MASK_KMSG = 1 << LOG_TYPE_KMSG,
+};
+
+#define log_full(level, ...) \
+ do { \
+ log_write((level), __FILE__, __LINE__, __func__, __VA_ARGS__); \
+ } while (0)
+
+void set_log_level(int level);
+int get_log_level(void);
+int log_open(enum log_mask log_set, const char *path);
+int log_close(void);
+int log_write(int level, const char*file, int line, const char *func, const char *format, ...);
+int log_move(const char *to);
+enum log_mask parse_log_type(const char *type);
+int config_parse_log_type(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data);
+
+#define log_dbg(format, ...) \
+ do { \
+ if (get_log_level() >= LOG_DEBUG) \
+ log_full(LOG_DEBUG, format, ##__VA_ARGS__); \
+ } while (0)
+
+#define log_err(format, ...) \
+ do { \
+ if (get_log_level() >= LOG_ERR) \
+ log_full(LOG_ERR, format, ##__VA_ARGS__); \
+ } while (0)
+
+#define log_info(format, ...) \
+ do { \
+ if (get_log_level() >= LOG_INFO) \
+ log_full(LOG_INFO, format, ##__VA_ARGS__); \
+ } while (0)
--- /dev/null
+/50-system-recovery.list
+/recovery-init
\ No newline at end of file
--- /dev/null
+# ---- Target contents ----------------------------------------------------- #
+DIRECTORIES="
+/usr/lib/bufmgr
+/usr/lib/tdm
+"
+
+DIR_SYMLINKS="
+"
+
+MVWITHLIBS="
+"
+
+WITHLIBS="
+/usr/lib/bufmgr/libtbm_sprd.so.0.0.0
+/usr/lib/tdm/libtdm-sprd.so
+"
+
+# LinkFileName:Target
+SYMLINKS="
+/usr/lib/bufmgr/libtbm_default.so:libtbm_sprd.so
+/usr/lib/bufmgr/libtbm_sprd.so.0:libtbm_sprd.so.0.0.0
+/usr/lib/bufmgr/libtbm_sprd.so:libtbm_sprd.so.0.0.0
+/usr/lib/tdm/libtdm-default.so:libtdm-sprd.so
+"
--- /dev/null
+# ---- Target contents ----------------------------------------------------- #
+DIRECTORIES="
+/dev
+/etc
+/proc
+/smack
+/sys
+/system
+/tmp
+/usr/bin
+/usr/lib
+/usr/sbin
+"
+
+MVWITHLIBS="
+@SYSTEM_RECOVERY_LIBEXEC_DIR@/recovery-init
+@INITRD_RECOVERY_LIBEXEC_DIR@/minireboot
+m4_ifdef(`RECOVERY_GUI',
+`@SYSTEM_RECOVERY_IMAGE_DIR@/font.png
+@SYSTEM_RECOVERY_IMAGE_DIR@/menu-title.png
+@SYSTEM_RECOVERY_IMAGE_DIR@/tizen-anim.png
+@SYSTEM_RECOVERY_IMAGE_DIR@/warning.png')
+m4_ifdef(`RECOVERY_GUI', `@SYSTEM_RECOVERY_LIBEXEC_DIR@/system-recovery.gui', `@SYSTEM_RECOVERY_LIBEXEC_DIR@/system-recovery.non_gui')
+"
+
+WITHLIBS="
+/usr/bin/bash
+/usr/bin/mount
+/usr/bin/sync
+/usr/bin/touch
+/usr/bin/umount
+/usr/sbin/blkid
+/usr/bin/ls
+/usr/sbin/agetty
+"
+
+VERBATIMS="
+@SYSTEM_RECOVERY_DATA_DIR@/system-recovery.cfg
+"
+
+# LinkFileName:Target
+SYMLINKS="
+/sbin/recovery-init:@SYSTEM_RECOVERY_LIBEXEC_DIR@/recovery-init
+"
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _POSIX_SOURCE
+
+#include <errno.h>
+#include <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/wait.h>
+#include <sys/types.h>
+
+#include "process-util.h"
+#include "system-recovery.h" /* For LOGD */
+
+int process_exec(process_exec_type sync, char *argv[])
+{
+ pid_t pid;
+ struct sigaction act, oldact;
+ int r = 0;
+
+ if (!argv)
+ return -EINVAL;
+
+ /* Use default signal handler */
+ act.sa_handler = SIG_DFL;
+ act.sa_flags = 0;
+ sigemptyset(&act.sa_mask);
+
+ if (sigaction(SIGCHLD, &act, &oldact) < 0)
+ return -errno;
+
+ pid = fork();
+ if (pid < 0) { /* Error */
+ LOGD("Failed to fork\n");
+ r = -errno;
+ } else if (!pid) { /* Child */
+ int i;
+
+ for (i = 0; i < _NSIG; i++)
+ signal(i, SIG_DFL);
+
+ r = execv(argv[0], (char **)argv);
+ if (r < 0)
+ exit(EXIT_FAILURE);
+ } else { /* Parent */
+ int status;
+
+ if (sync == PROCESS_NON_WAIT)
+ return pid;
+
+ /* Wait for child */
+ if (waitpid(pid, &status, 0) != -1) {
+ if (WIFEXITED(status)) { /* Terminated normally */
+ LOGD("%d terminated by exit(%d)\n", pid,
+ WEXITSTATUS(status));
+ return WEXITSTATUS(status);
+ } else if (WIFSIGNALED(status))
+ LOGD("%d terminated by signal %d\n", pid,
+ WTERMSIG(status));
+ else if (WIFSTOPPED(status))
+ LOGD("%d stopped by signal %d\n", pid,
+ WSTOPSIG(status));
+ } else
+ LOGD("%d waitpid() failed - %d\n", pid, errno);
+ }
+
+ if (sigaction(SIGCHLD, &oldact, NULL) < 0)
+ LOGD("failed to restore sigaction\n");
+
+ return r;
+}
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ PROCESS_NON_WAIT,
+ PROCESS_WAIT_CHILD
+} process_exec_type;
+
+int process_exec(process_exec_type sync, char *argv[]);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+#!/bin/sh
+
+CONFIG_FILE="@SYSTEM_RECOVERY_DATA_DIR@/system-recovery.cfg"
+ACTION_FILE="@SYSTEM_RECOVERY_ACTION_FILE@"
+
+actions=`cat $CONFIG_FILE | sed -ne '/^action_handlers[[:space:]]*=[[:space:]]*{/,/}/ p' | sed -ne 's/[[:space:]]*\(.*\)[[:space:]]*=[[:space:]]*\".*/\1/ p'`
+
+for a in ${actions}
+do
+ if [ "$a" = "${1}" ]
+ then
+ echo "${1}" > $ACTION_FILE
+ echo "Action changed to ${1}"
+ exit
+ fi
+done
+
+echo "Action ${1} is not specified in configuration."
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libconfig.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <errno.h>
+
+#include "config.h"
+#include "log.h"
+#include "system-recovery.h"
+
+static char *get_action_from_config(config_t *cfg)
+{
+ config_setting_t *node;
+ const char *action;
+
+ node = config_lookup(cfg, "headless_action");
+ if (!node)
+ return NULL;
+
+ action = config_setting_get_string(node);
+
+ return strdup(action);
+}
+
+int recovery_headless(config_t *cfg)
+{
+ config_setting_t *node;
+
+ node = config_lookup(cfg, "action_handlers");
+ if (!node)
+ return -ENOENT;
+
+ char *action = get_action_from_cmdline();
+ if (!action)
+ action = get_action_from_file();
+ if (!action)
+ action = get_action_from_config(cfg);
+ if (!action)
+ return -ENOENT;
+
+ const char *handler;
+ int r = config_setting_lookup_string(node, action, &handler);
+ free(action);
+
+ if (r == CONFIG_FALSE)
+ return -ENOENT;
+
+ return system(handler);
+}
--- /dev/null
+#!/bin/sh
+
+SYSTEM_RECOVERY_GUI="@SYSTEM_RECOVERY_LIBEXEC_DIR@/system-recovery.gui"
+SYSTEM_RECOVERY_NON_GUI="@SYSTEM_RECOVERY_LIBEXEC_DIR@/system-recovery.non_gui"
+FAKE_ROOT=/system
+
+MOUNT="/usr/bin/mount"
+BLKID="/usr/sbin/blkid"
+REBOOT="@INITRD_RECOVERY_LIBEXEC_DIR@/minireboot"
+SYNC="/usr/bin/sync"
+UMOUNT="/usr/bin/umount"
+
+#------------------------------------------------
+# get partition id
+#------------------------------------------------
+get_partition_id() {
+ PART_ROOTFS=$("$BLKID" --match-token PARTLABEL=ROOTFS -o device || "$BLKID" --match-token LABEL=rootfs -o device)
+ PART_SYSTEM_DATA=$("$BLKID" --match-token PARTLABEL=SYSTEM-DATA -o device || "$BLKID" --match-token LABEL=system-data -o device)
+ PART_USER=$("$BLKID" --match-token PARTLABEL=USER -o device || "$BLKID" --match-token LABEL=user -o device)
+}
+
+#------------------------------------------------
+# mount_partitions
+#------------------------------------------------
+mount_partitions() {
+ echo "mount partitions"
+ get_partition_id
+
+ "$MOUNT" -t ext4 ${PART_ROOTFS} ${FAKE_ROOT} -o ro
+ "$MOUNT" -t ext4 ${PART_SYSTEM_DATA} ${FAKE_ROOT}/opt
+ "$MOUNT" -t ext4 ${PART_USER} ${FAKE_ROOT}/opt/usr
+
+ "$MOUNT" -t proc none ${FAKE_ROOT}/proc
+ "$MOUNT" -t sysfs none ${FAKE_ROOT}/sys
+ "$MOUNT" -t smackfs smackfs ${FAKE_ROOT}/sys/fs/smackfs
+ "$MOUNT" -t devtmpfs devtmpfs ${FAKE_ROOT}/dev
+ "$MOUNT" -t devpts devpts ${FAKE_ROOT}/dev/pts
+ "$MOUNT" -t tmpfs tmpfs ${FAKE_ROOT}/tmp -o mode=1777,smackfsroot=*
+}
+
+#------------------------------------------------
+# umount_partitions
+#------------------------------------------------
+umount_partitions() {
+ echo "umount partitions"
+ "$SYNC"
+
+ "$UMOUNT" ${FAKE_ROOT}/opt/usr
+ "$UMOUNT" ${FAKE_ROOT}/opt
+ "$UMOUNT" ${FAKE_ROOT}
+}
+
+#------------------------------------------------
+# do_reboot
+#------------------------------------------------
+do_reboot() {
+ echo "Reboot"
+ "$SYNC"
+ "$REBOOT"
+ while [ 1 ]
+ do
+ sleep 1
+ echo "."
+ done
+}
+
+#------------------------------------------------
+# system-recovery initrc
+#------------------------------------------------
+echo "Starting system recovery."
+mount_partitions
+
+# For debugging - It should be deleted on Release
+/sbin/agetty -l /bin/sh -n --keep-baud 115200,38400,9600 ttyS1 linux &
+
+[ -x "${SYSTEM_RECOVERY_GUI}" ] && "${SYSTEM_RECOVERY_GUI}" || "${SYSTEM_RECOVERY_NON_GUI}"
+
+umount_partitions
+do_reboot
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _POSIX_SOURCE
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <libconfig.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/reboot.h>
+
+#include <asm-generic/setup.h> // for COMMAND_LINE_SIZE
+
+#include "system-recovery.h"
+
+void sys_power_reboot(void)
+{
+ reboot(RB_AUTOBOOT);
+}
+
+#define KERNEL_CMDLINE_KEY "tizen.recovery"
+#define ACTION_BUFFER_SIZE 256
+#define _STR(x) #x
+#define STR(x) _STR(x)
+
+// looks for tizen.recovery= key in kernel command line
+char *get_action_from_cmdline(void)
+{
+ FILE *fp;
+ char cmdline[COMMAND_LINE_SIZE];
+ int len;
+
+ fp = fopen("/proc/cmdline", "r");
+ if (!fp)
+ return NULL;
+
+ char *p = fgets(cmdline, sizeof cmdline, fp);
+ fclose(fp);
+ if (!p)
+ return NULL;
+
+ const char *prefix = KERNEL_CMDLINE_KEY "=";
+ p = strstr(cmdline, prefix);
+ if (!p)
+ return NULL;
+ p += strlen(prefix);
+
+ for (len = 0; *(p + len) != 0 && !isspace(*(p + len)); ++len)
+ ; /* skip */
+
+ return strndup(p, len);
+}
+
+char *get_action_from_file(void)
+{
+ FILE *fp;
+ char buf[ACTION_BUFFER_SIZE];
+ int ret;
+
+ fp = fopen(SYSTEM_RECOVERY_ACTION_FILE, "r");
+ if (!fp) {
+ LOGD("Could not open recovery action file\n");
+ return NULL;
+ }
+
+ ret = fscanf(fp, "%" STR(ACTION_BUFFER_SIZE) "s", buf);
+ fclose(fp);
+ if (unlink(SYSTEM_RECOVERY_ACTION_FILE) < 0)
+ LOGD("Could not unlink recovery action file: %m\n");
+
+ if (ret != 1)
+ return NULL;
+
+ return strndup(buf, ACTION_BUFFER_SIZE);
+}
+
+int main(void)
+{
+ config_t cfg;
+ int ret;
+
+ LOGD("[main] recovery started.\n");
+
+ config_init(&cfg);
+ ret = config_read_file(&cfg, SYSTEM_RECOVERY_CONFIG_FILE);
+ if (ret == CONFIG_FALSE) {
+ LOGD("Can't read config file");
+ return 1;
+ }
+
+#ifdef RECOVERY_GUI
+ ret = recovery_gui(&cfg);
+#else
+ ret = recovery_headless(&cfg);
+#endif
+
+ LOGD("[main] recovery finished.\n");
+ config_destroy(&cfg);
+
+ return ret;
+}
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "graphics.h"
+
+#define RUI_COLOR_BACKGROUND BLACK
+#define RUI_COLOR_TITLE (color) { .r = 27, .g = 199, .b = 204, .a = 255 }
+#define RUI_COLOR_RULER RUI_COLOR_TITLE
+
+#define RUI_COLOR_MENU_BG_SELECTED RUI_COLOR_TITLE
+#define RUI_COLOR_MENU_BG_UNSELECTED BLACK
+#define RUI_COLOR_MENU_TEXT_SELECTED WHITE
+#define RUI_COLOR_MENU_TEXT_UNSELECTED WHITE
+
+#define RUI_COLOR_DESCRIPTION_TITLE RUI_COLOR_TITLE
+#define RUI_COLOR_DESCRIPTION_TEXT WHITE
+
+#define RUI_COLOR_PROGRESS_BAR_BAR YELLOW
+#define RUI_COLOR_PROGRESS_BAR_BORDER RUI_COLOR_TITLE
+#define RUI_COLOR_PROGRESS_BAR_BACKGROUND BLACK
+
+#ifdef FEATURE_DISPLAY_720X1280
+#define RUI_MENU_ITEM_HEIGHT 60
+#define RUI_MENU_ITEM_SPACING 8
+#define RUI_MENU_TEXT_POS_X 15
+
+#define RUI_COMMON_MENU_POS_X 0
+
+#define RUI_MAIN_MENU_POS_X RUI_COMMON_MENU_POS_X
+#define RUI_MAIN_MENU_POS_Y 100
+
+#define RUI_REBOOT_MENU_POS_X RUI_COMMON_MENU_POS_X
+#define RUI_REBOOT_MENU_POS_Y 480
+
+#define RUI_SAFE_MENU_POS_X RUI_COMMON_MENU_POS_X
+#define RUI_SAFE_MENU_POS_Y 480
+
+#define RUI_FACTORY_MENU_POS_X RUI_COMMON_MENU_POS_X
+#define RUI_FACTORY_MENU_POS_Y 480
+
+#define RUI_SD_RESTORE_MENU_POS_X RUI_COMMON_MENU_POS_X
+#define RUI_SD_RESTORE_MENU_POS_Y 480
+
+#define RUI_MAIN_SCREEN_DESCRIPTION_POS_X 15
+#define RUI_MAIN_SCREEN_DESCRIPTION_POS_Y 480
+
+#define RUI_COMMON_SCREEN_DESCRIPTION_POS_X 15
+#define RUI_COMMON_SCREEN_DESCRIPTION_POS_Y 100
+
+#define RUI_RULER_HEIGHT 2
+
+#define RUI_RULER_TOP_POS_X 0
+#define RUI_RULER_TOP_POS_Y 80
+#define RUI_MAIN_SCREEN_RULER_POS_Y 420
+
+#define RUI_PROGRESS_BAR_BORDER_WIDTH 1
+#define RUI_PROGRESS_BAR_HEIGHT 20
+
+#define RUI_SD_RESTORE_RUN_SCREEN_PROGRESS_BAR_POS_X 5
+#define RUI_SD_RESTORE_RUN_SCREEN_PROGRESS_BAR_POS_Y 600
+
+#else
+#define RUI_MENU_ITEM_HEIGHT 50
+#define RUI_MENU_ITEM_SPACING 5
+#define RUI_MENU_TEXT_POS_X 5
+
+#define RUI_COMMON_MENU_POS_X 0
+
+#define RUI_MAIN_MENU_POS_X RUI_COMMON_MENU_POS_X
+#define RUI_MAIN_MENU_POS_Y 100
+
+#define RUI_REBOOT_MENU_POS_X RUI_COMMON_MENU_POS_X
+#define RUI_REBOOT_MENU_POS_Y 160
+
+#define RUI_SAFE_MENU_POS_X RUI_COMMON_MENU_POS_X
+#define RUI_SAFE_MENU_POS_Y 240
+
+#define RUI_FACTORY_MENU_POS_X RUI_COMMON_MENU_POS_X
+#define RUI_FACTORY_MENU_POS_Y 240
+
+#define RUI_SD_RESTORE_MENU_POS_X RUI_COMMON_MENU_POS_X
+#define RUI_SD_RESTORE_MENU_POS_Y 240
+
+#define RUI_MAIN_SCREEN_DESCRIPTION_POS_X 5
+#define RUI_MAIN_SCREEN_DESCRIPTION_POS_Y 372
+
+#define RUI_COMMON_SCREEN_DESCRIPTION_POS_X 5
+#define RUI_COMMON_SCREEN_DESCRIPTION_POS_Y 100
+
+#define RUI_RULER_HEIGHT 2
+
+#define RUI_RULER_TOP_POS_X 0
+#define RUI_RULER_TOP_POS_Y 60
+#define RUI_MAIN_SCREEN_RULER_POS_Y 347
+
+#define RUI_PROGRESS_BAR_BORDER_WIDTH 1
+#define RUI_PROGRESS_BAR_HEIGHT 20
+
+#define RUI_SD_RESTORE_RUN_SCREEN_PROGRESS_BAR_POS_X 5
+#define RUI_SD_RESTORE_RUN_SCREEN_PROGRESS_BAR_POS_Y 600
+#endif
+
+#define RUI_REBOOT_SCREEN_DESCRIPTION_POS_X RUI_COMMON_SCREEN_DESCRIPTION_POS_X
+#define RUI_REBOOT_SCREEN_DESCRIPTION_POS_Y RUI_COMMON_SCREEN_DESCRIPTION_POS_Y
+
+#define RUI_SAFE_SCREEN_DESCRIPTION_POS_X RUI_COMMON_SCREEN_DESCRIPTION_POS_X
+#define RUI_SAFE_SCREEN_DESCRIPTION_POS_Y RUI_COMMON_SCREEN_DESCRIPTION_POS_Y
+
+#define RUI_FACTORY_SCREEN_DESCRIPTION_POS_X RUI_COMMON_SCREEN_DESCRIPTION_POS_X
+#define RUI_FACTORY_SCREEN_DESCRIPTION_POS_Y RUI_COMMON_SCREEN_DESCRIPTION_POS_Y
+
+#define RUI_FACTORY_RUN_SCREEN_DESCRIPTION_POS_X RUI_COMMON_SCREEN_DESCRIPTION_POS_X
+#define RUI_FACTORY_RUN_SCREEN_DESCRIPTION_POS_Y RUI_COMMON_SCREEN_DESCRIPTION_POS_Y
+
+#define RUI_SD_RESTORE_SCREEN_DESCRIPTION_POS_X RUI_COMMON_SCREEN_DESCRIPTION_POS_X
+#define RUI_SD_RESTORE_SCREEN_DESCRIPTION_POS_Y RUI_COMMON_SCREEN_DESCRIPTION_POS_Y
+
+#define RUI_SD_RESTORE_RUN_SCREEN_DESCRIPTION_POS_X RUI_COMMON_SCREEN_DESCRIPTION_POS_X
+#define RUI_SD_RESTORE_RUN_SCREEN_DESCRIPTION_POS_Y RUI_COMMON_SCREEN_DESCRIPTION_POS_Y
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libconfig.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <errno.h>
+
+#include "rui.h"
+#include "common.h"
+#include "config.h"
+#include "rui-menu.h"
+#include "graphics.h"
+#include "log.h"
+#include "rui-image.h"
+#include "rui-ruler.h"
+#include "input-events.h"
+#include "rui-description.h"
+#include "system-recovery.h"
+#include "rui-progress-bar.h"
+#include "recovery-rui-skin.h"
+#include "process-util.h"
+
+/* if user does not do anything, default action will be taken after this timeout*/
+#define DEFAULT_ACTION_TIMEOUT 4
+
+#define BUFFER_SIZE 512
+
+bool volatile running = true;
+static const char *original_description = NULL;
+static char description_buffer[BUFFER_SIZE];
+static char *rui_default_action = NULL;
+static const char *rui_default_handler = NULL;
+
+static int timer_count = 0;
+static bool user_idle = true;
+
+static void timeout_handler(rui_screen *cs)
+{
+ int ret;
+
+ if (rui_default_action && user_idle) {
+ if (!original_description) {
+ original_description = cs->description->text;
+ cs->description->text = description_buffer;
+ }
+
+ snprintf(description_buffer, BUFFER_SIZE,
+ "%s\nDefault action (%s) will be taken after %d seconds",
+ original_description, rui_default_action,
+ DEFAULT_ACTION_TIMEOUT - timer_count/TIMER_INTERVAL);
+
+ if (timer_count/TIMER_INTERVAL == DEFAULT_ACTION_TIMEOUT) {
+ ret = system(rui_default_handler);
+ if (ret < 0)
+ LOGD("Could not run action: %s\n", rui_default_handler);
+ }
+ }
+
+ if (original_description && !user_idle) {
+ cs->description->text = original_description;
+ original_description = NULL;
+ }
+
+ timer_count++;
+}
+
+void recovery_rui_input_callback(user_action action, user_action_type action_type)
+{
+ int need_repaint = 1;
+ rui_screen *cs;
+
+ /* We interested only in button downs, long presses and idle events */
+ if (action_type != ACTION_TYPE_BEGIN &&
+ action_type != ACTION_TYPE_LONGPRESS &&
+ action_type != ACTION_TYPE_IDLE &&
+ action_type != ACTION_TYPE_TIMER)
+ return;
+
+ cs = get_current_screen();
+ if (action_type != ACTION_TYPE_TIMER &&
+ action_type != ACTION_TYPE_IDLE &&
+ user_idle) {
+ user_idle = false;
+ timeout_handler(cs);
+ }
+
+ if (action == ACTION_DOWN && cs->menu)
+ rui_menu_cursor_down(cs->menu);
+ else if (action == ACTION_UP && cs->menu)
+ rui_menu_cursor_up(cs->menu);
+ else if (cs->allow_force_reboot &&
+ action == ACTION_CONFIRM &&
+ action_type == ACTION_TYPE_LONGPRESS)
+ sys_power_reboot();
+ else if ((action == ACTION_CONFIRM || action == ACTION_HOME) &&
+ cs->menu)
+ rui_menu_action_run(cs->menu);
+ else if (action == ACTION_BACK)
+ rui_screen_switch(RUI_SCREEN_BACK);
+ else if (action == ACTION_TIMEOUT)
+ timeout_handler(cs);
+ else if (action != ACTION_NONE || action_type != ACTION_TYPE_IDLE ||
+ !cs->animations)
+ need_repaint = 0;
+
+ if (need_repaint)
+ rui_draw();
+}
+
+static struct {
+ const char **rui_screens;
+ const char **rui_menus;
+ const char **rui_animations;
+ const char **rui_images;
+ const char **rui_colors;
+ const char **rui_screen_styles;
+ const char **rui_menu_styles;
+ const char **rui_ruler_styles;
+ const char **rui_rulers;
+ const char **rui_description_styles;
+ const char **rui_descriptions;
+ const char **rui_action_handlers;
+} rui_config_labels;
+
+static rui_screen *rui_screens = NULL;
+static rui_menu *rui_menus = NULL;
+static rui_screen_style *rui_screen_styles = NULL;
+static rui_menu_style *rui_menu_styles = NULL;
+static rui_ruler_style *rui_ruler_styles = NULL;
+static rui_animation *rui_animations = NULL;
+static rui_image *rui_images = NULL;
+static color *rui_colors = NULL;
+static rui_ruler **rui_rulers = NULL;
+static rui_description_style *rui_description_styles = NULL;
+static rui_description *rui_descriptions = NULL;
+static const char **rui_action_handlers = NULL;
+
+/* naive search */
+int find_string(const char **list, const char *s)
+{
+ int i;
+
+ if (!list)
+ return -EINVAL;
+
+ for (i = 0; list[i]; ++i)
+ if (strcmp(list[i], s) == 0)
+ return i;
+
+ return -ENOENT;
+}
+
+static inline int _rui_lookup_setting(config_setting_t *root, const char **labels, const char *name)
+{
+ const char *value;
+ int ret;
+
+ ret = config_setting_lookup_string(root, name, &value);
+ if (ret == CONFIG_FALSE)
+ return -1;
+
+ return find_string(labels, value);
+}
+
+#define rui_lookup_setting(root, list, out, field) do { \
+ int _idx = _rui_lookup_setting(root, rui_config_labels.list, #field); \
+ if (_idx < 0 || !list) { \
+ (out)->field = NULL; \
+ log_dbg("Could not find setting %s.%s", #out, #field); \
+ } else \
+ (out)->field = &list[_idx]; \
+ } while (0)
+
+#define rui_lookup_setting_value(root, list, out, field) do { \
+ int _idx = _rui_lookup_setting(root, rui_config_labels.list, #field); \
+ if (_idx < 0 || !list) \
+ log_dbg("Could not find setting %s.%s", #out, #field); \
+ else \
+ out->field = list[_idx]; \
+ } while (0)
+
+static inline int ascii_hex(char c)
+{
+ switch (c) {
+ case '0' ... '9':
+ return c - '0';
+ case 'A' ... 'F':
+ return c - 'A' + 10;
+ case 'a' ... 'f':
+ return c - 'a' + 10;
+ }
+
+ return 0;
+}
+
+static inline char get_hex_byte(const char *s)
+{
+ return 16 * ascii_hex(s[0]) + ascii_hex(s[1]);
+}
+
+static int color_entry_parse(config_setting_t *root, void *data)
+{
+ color *c = data;
+ const char *str;
+
+ str = config_setting_get_string(root);
+ if (!str)
+ return -ENOENT;
+
+ if (strlen(str) == 9 && str[0] == '#') {
+ c->r = get_hex_byte(str + 1);
+ c->g = get_hex_byte(str + 3);
+ c->b = get_hex_byte(str + 5);
+ c->a = get_hex_byte(str + 7);
+
+ return 0;
+ }
+
+ return -ENOTSUP;
+}
+
+struct str2int_map {
+ const char *key;
+ int value;
+};
+
+static int map_find(const char *key, struct str2int_map *map)
+{
+ int i;
+
+ for (i = 0; map[i].key; ++i)
+ if (strcmp(key, map[i].key) == 0)
+ return map[i].value;
+
+ return -1;
+}
+
+static struct str2int_map align_hor_map[] = {
+ {"left", GR_ALIGN_LEFT},
+ {"center", GR_ALIGN_CENTER},
+ {"right", GR_ALIGN_RIGHT},
+ {NULL, 0}
+};
+
+static struct str2int_map align_ver_map[] = {
+ {"top", GR_ALIGN_TOP},
+ {"middle", GR_ALIGN_MIDDLE},
+ {"bottom", GR_ALIGN_BOTTOM},
+ {NULL, 0}
+};
+
+static struct str2int_map img_type_map[] = {
+ {"no-alpha", GR_WITHOUT_ALPHA},
+ {"alpha", GR_WITH_ALPHA},
+ {NULL, 0}
+};
+
+static int image_entry_parse(config_setting_t *root, void *data)
+{
+ rui_image *image = data;
+ const char *value;
+ int ret;
+
+ ret = config_setting_lookup_string(root, "fname", &image->fname);
+ if (ret == CONFIG_FALSE)
+ return -1;
+
+ rui_lookup_setting_value(root, rui_colors, image, c_bg);
+
+ ret = config_setting_lookup_string(root, "align_hor", &value);
+ image->align_hor = map_find(value, align_hor_map);
+
+ ret = config_setting_lookup_string(root, "align_ver", &value);
+ image->align_ver = map_find(value, align_ver_map);
+
+ config_setting_lookup_int(root, "offset_x", &image->offset_x);
+ config_setting_lookup_int(root, "offset_y", &image->offset_y);
+
+ ret = config_setting_lookup_string(root, "img_type", &value);
+ image->img_type = map_find(value, img_type_map);
+
+ image->surface = NULL;
+
+ return 0;
+}
+
+static int animation_entry_parse(config_setting_t *root, void *data)
+{
+ rui_animation *animation = data;
+ const char *value;
+ int ret;
+
+ ret = config_setting_lookup_string(root, "fname", &animation->fname);
+ if (ret == CONFIG_FALSE)
+ return -1;
+
+ rui_lookup_setting_value(root, rui_colors, animation, c_bg);
+
+ ret = config_setting_lookup_string(root, "align_hor", &value);
+ animation->align_hor = map_find(value, align_hor_map);
+
+ ret = config_setting_lookup_string(root, "align_ver", &value);
+ animation->align_ver = map_find(value, align_ver_map);
+
+ config_setting_lookup_int(root, "offset_x", &animation->offset_x);
+ config_setting_lookup_int(root, "offset_y", &animation->offset_y);
+ config_setting_lookup_int(root, "frames_num", &animation->frames_num);
+ config_setting_lookup_int(root, "icurrent_frame", &animation->frames_num);
+
+ ret = config_setting_lookup_string(root, "img_type", &value);
+ animation->img_type = map_find(value, img_type_map);
+
+ animation->surfaces = NULL;
+
+ return 0;
+}
+
+static int get_screen_id(config_setting_t *root, const char *key)
+{
+ int ret;
+ static const char *special_labels[] = {
+ "",
+ "CURRENT",
+ "BACK",
+ };
+
+ ret = _rui_lookup_setting(root,
+ rui_config_labels.rui_screens, key);
+ if (ret != -ENOENT)
+ return ret;
+
+ ret = _rui_lookup_setting(root, special_labels, key);
+ if (ret < 0) {
+ log_err("Could not get screen id");
+ return RUI_SCREEN_CURRENT;
+ } else {
+ return -ret;
+ }
+}
+
+static int menu_entry_parse(config_setting_t *root, void *data)
+{
+ config_setting_t *actions, *node;
+ rui_menu *menu = data;
+ int i;
+ int ret;
+
+ rui_lookup_setting(root, rui_menu_styles, menu, style);
+
+ config_setting_lookup_int(root, "pos_x", &menu->pos_x);
+ config_setting_lookup_int(root, "pos_y", &menu->pos_y);
+ config_setting_lookup_int(root, "item_selected", &menu->item_selected);
+ config_setting_lookup_int(root, "item_default", &menu->item_default);
+
+ actions = config_setting_get_member(root, "actions");
+ if (!actions)
+ return 0;
+
+ menu->items_num = config_setting_length(actions);
+ menu->items = calloc(menu->items_num, sizeof(*menu->items));
+ menu->actions = calloc(menu->items_num, sizeof(*menu->actions));
+ if (!menu->items || !menu->actions) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ for (i = 0; i < menu->items_num; ++i) {
+ node = config_setting_get_elem(actions, i);
+ if (!node) {
+ log_err("Could not get next setting");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ config_setting_lookup_string(node, "label", &menu->items[i]);
+ menu->actions[i].screen_switch_to = get_screen_id(node, "screen_switch_to");
+ config_setting_lookup_int(node, "exit_after_action", &menu->actions[i].exit_after_action);
+ rui_lookup_setting_value(node, rui_action_handlers, (&menu->actions[i]), action_handler);
+ }
+
+ return 0;
+
+err:
+ free(menu->items);
+ free(menu->actions);
+ return ret;
+}
+
+static int description_style_entry_parse(config_setting_t *root, void *data)
+{
+ rui_description_style *style = data;
+ rui_lookup_setting_value(root, rui_colors, style, c_title);
+ rui_lookup_setting_value(root, rui_colors, style, c_text);
+
+ return 0;
+}
+
+static int description_entry_parse(config_setting_t *root, void *data)
+{
+ rui_description *desc = data;
+
+ config_setting_lookup_int(root, "pos_x", &desc->pos_x);
+ config_setting_lookup_int(root, "pos_y", &desc->pos_y);
+ rui_lookup_setting(root, rui_description_styles, desc, style);
+ config_setting_lookup_string(root, "title", &desc->title);
+ config_setting_lookup_string(root, "text", &desc->text);
+
+ return 0;
+}
+
+static int labels_list_parse(config_setting_t *root, int **out,
+ const char *name, const char **labels)
+{
+ int i;
+ int num;
+ int *list;
+ config_setting_t *elem, *node;
+ const char *value;
+
+ node = config_setting_get_member(root, name);
+ if (!node)
+ return 0;
+
+ num = config_setting_length(node);
+ if (num < 0)
+ return -EINVAL;
+
+ list = calloc(num + 1, sizeof(*list));
+ if (!list)
+ return -ENOMEM;
+
+ for (i = 0; i < num; ++i) {
+ elem = config_setting_get_elem(node, i);
+ if (!elem)
+ goto err_nomem;
+
+ value = config_setting_get_string(elem);
+ if (!value)
+ goto err_nomem;
+
+ list[i] = find_string(labels, value);
+ }
+
+ list[num] = -1;
+
+ *out = list;
+ return 0;
+
+err_nomem:
+ free(list);
+ return -ENOMEM;
+}
+
+static int screen_entry_parse(config_setting_t *root, void *data)
+{
+ rui_screen *screen = data;
+
+ rui_lookup_setting(root, rui_screen_styles, screen, style);
+ rui_lookup_setting(root, rui_menus, screen, menu);
+ rui_lookup_setting_value(root, rui_rulers, screen, rulers);
+ rui_lookup_setting(root, rui_descriptions, screen, description);
+
+ labels_list_parse(root, &screen->images, "images",
+ rui_config_labels.rui_images);
+ labels_list_parse(root, &screen->animations, "animations",
+ rui_config_labels.rui_animations);
+
+ screen->screen_back = get_screen_id(root, "screen_back");
+ config_setting_lookup_int(root, "allow_force_reboot", &screen->allow_force_reboot);
+
+ /*
+ screen->progress_bar = NULL;
+ screen->on_enter = NULL;
+ screen->draw = NULL;
+ */
+
+ return 0;
+}
+
+static int ruler_entry_parse(config_setting_t *root, void *data)
+{
+ rui_ruler *ruler = *(rui_ruler **)data;
+ config_setting_t *node;
+ int num;
+ int i;
+
+ num = config_setting_length(root);
+ if (num < 0)
+ return -EINVAL;
+
+ for (i = 0; i < num; ++i) {
+ node = config_setting_get_elem(root, i);
+ if (!node)
+ return -ENOMEM;
+
+ config_setting_lookup_int(node, "pos_x", &ruler[i].pos_x);
+ config_setting_lookup_int(node, "pos_y", &ruler[i].pos_y);
+ config_setting_lookup_int(node, "height", &ruler[i].height);
+ rui_lookup_setting(node, rui_ruler_styles, &ruler[i], style);
+ }
+
+ return 0;
+}
+
+static int ruler_entry_init(config_setting_t *root, void *data)
+{
+ rui_ruler **out = data;
+ rui_ruler *ruler;
+ int num;
+
+ num = config_setting_length(root);
+ if (num < 0)
+ return -EINVAL;
+
+ ruler = calloc(num + 1, sizeof(*ruler));
+ if (!ruler)
+ return -ENOMEM;
+
+ *out = ruler;
+ return 0;
+}
+
+static int screen_style_entry_parse(config_setting_t *root, void *data)
+{
+ rui_screen_style *style = data;
+
+ rui_lookup_setting_value(root, rui_colors, style, c_background);
+
+ return 0;
+}
+
+static int menu_style_entry_parse(config_setting_t *root, void *data)
+{
+ rui_menu_style *style = data;
+
+ config_setting_lookup_int(root, "item_height", &style->item_height);
+ config_setting_lookup_int(root, "item_spacing", &style->item_spacing);
+ config_setting_lookup_int(root, "text_pos_x", &style->text_pos_x);
+ rui_lookup_setting_value(root, rui_colors, style, c_bg_selected);
+ rui_lookup_setting_value(root, rui_colors, style, c_bg_unselected);
+ rui_lookup_setting_value(root, rui_colors, style, c_text_selected);
+ rui_lookup_setting_value(root, rui_colors, style, c_text_unselected);
+
+ return 0;
+}
+
+static int ruler_style_entry_parse(config_setting_t *root, void *data)
+{
+ rui_ruler_style *style = data;
+
+ rui_lookup_setting_value(root, rui_colors, style, c_ruler);
+
+ return 0;
+}
+
+static int action_handler_entry_parse(config_setting_t *root, void *data)
+{
+ const char **handler = data;
+
+ *handler = config_setting_get_string(root);
+ return 0;
+}
+
+static int rui_config_group_init(config_t *cfg, const char *group_name,
+ int (*entry_init)(config_setting_t *root, void *out),
+ void **out, size_t entry_size, const char ***labels)
+{
+ int num, i;
+ config_setting_t *root, *node;
+ char *data;
+ const char **labels_data;
+ int ret;
+
+ root = config_lookup(cfg, group_name);
+ if (!root) {
+ log_err("Could not find %s group in config", group_name);
+ return -ENOENT;
+ }
+
+ num = config_setting_length(root);
+ if (num <= 0)
+ return 0;
+
+ data = calloc(num, entry_size);
+ labels_data = calloc(num + 1, sizeof(*labels_data));
+ if (!data || !labels_data) {
+ log_err("Could not allocate memory");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ for (i = 0; i < num; ++i) {
+ node = config_setting_get_elem(root, i);
+ if (!node) {
+ log_err("Could not get next setting");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ labels_data[i] = config_setting_name(node);
+
+ if (entry_init) {
+ ret = entry_init(node, data + i * entry_size);
+ if (ret < 0)
+ goto err;
+ }
+ }
+
+ *out = data;
+ *labels = labels_data;
+ return num;
+
+err:
+ free(data);
+ free(labels_data);
+ return ret;
+}
+
+static int rui_config_group_parse(config_t *cfg, const char *group_name,
+ int (*entry_parse)(config_setting_t *root, void *out),
+ char *data, size_t entry_size)
+{
+ int num, i;
+ config_setting_t *root, *node;
+ int ret;
+
+ root = config_lookup(cfg, group_name);
+ if (!root) {
+ log_err("Could not find %s group in config", group_name);
+ return -ENOENT;
+ }
+
+ num = config_setting_length(root);
+ if (num <= 0)
+ return 0;
+
+ for (i = 0; i < num; ++i) {
+ node = config_setting_get_elem(root, i);
+ if (!node) {
+ log_err("Could not get next setting");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ ret = entry_parse(node, data + i * entry_size);
+ if (ret < 0)
+ goto err;
+ }
+
+ return num;
+
+err:
+ return ret;
+}
+
+bool recovery_rui_init(config_t *cfg)
+{
+ int main_screen_n = 0;
+ int i;
+
+#define DECLARE_GROUP(n, g, h) { \
+ .name = n, \
+ .out = (void **)&g, \
+ .entry_size = sizeof(*g), \
+ .entry_init = NULL, \
+ .entry_parse = h, \
+ .labels = &rui_config_labels.g \
+}
+
+#define DECLARE_GROUP_INIT(n, g, i, h) { \
+ .name = n, \
+ .out = (void **)&g, \
+ .entry_size = sizeof(*g), \
+ .entry_init = i, \
+ .entry_parse = h, \
+ .labels = &rui_config_labels.g \
+}
+
+ static struct {
+ const char *name;
+ void **out;
+ size_t entry_size;
+ int (*entry_init)(config_setting_t *root, void *out);
+ int (*entry_parse)(config_setting_t *root, void *out);
+ const char ***labels;
+
+ int num;
+ } groups[] = {
+ DECLARE_GROUP("screens", rui_screens, screen_entry_parse),
+ DECLARE_GROUP("images", rui_images, image_entry_parse),
+ DECLARE_GROUP("animations", rui_animations, animation_entry_parse),
+ DECLARE_GROUP("action_handlers", rui_action_handlers, action_handler_entry_parse),
+ DECLARE_GROUP("menus", rui_menus, menu_entry_parse),
+ DECLARE_GROUP("colors", rui_colors, color_entry_parse),
+ DECLARE_GROUP("menu_styles", rui_menu_styles, menu_style_entry_parse),
+ DECLARE_GROUP("screen_styles", rui_screen_styles, screen_style_entry_parse),
+ DECLARE_GROUP("ruler_styles", rui_ruler_styles, ruler_style_entry_parse),
+ DECLARE_GROUP_INIT("rulers", rui_rulers, ruler_entry_init, ruler_entry_parse),
+ DECLARE_GROUP("description_styles", rui_description_styles, description_style_entry_parse),
+ DECLARE_GROUP("descriptions", rui_descriptions, description_entry_parse),
+ {NULL}
+
+ };
+#undef DECLARE_GROUP
+#undef DECLARE_GROUP_INIT
+
+ for (i = 0; groups[i].name; ++i)
+ groups[i].num = rui_config_group_init(cfg, groups[i].name, groups[i].entry_init,
+ groups[i].out, groups[i].entry_size, groups[i].labels);
+
+ for (i = 0; groups[i].name; ++i)
+ groups[i].num = rui_config_group_parse(cfg, groups[i].name, groups[i].entry_parse,
+ *(char **)groups[i].out, groups[i].entry_size);
+
+ return rui_init(rui_screens, groups[0].num,
+ main_screen_n,
+ rui_images, groups[1].num,
+ rui_animations, groups[2].num);
+}
+
+void cleanup_menus()
+{
+ int i;
+ if (!rui_menus)
+ return;
+
+ for (i = 0; rui_config_labels.rui_menus[i]; ++i) {
+ free(rui_menus[i].items);
+ free(rui_menus[i].actions);
+ }
+}
+
+void cleanup_rulers()
+{
+ int i;
+ if (!rui_rulers)
+ return;
+
+ for (i = 0; rui_config_labels.rui_rulers[i]; ++i)
+ free(rui_rulers[i]);
+}
+
+void cleanup_screens()
+{
+ int i;
+ if (!rui_screens)
+ return;
+
+ for (i = 0; rui_config_labels.rui_screens[i]; ++i)
+ free(rui_screens[i].images);
+}
+
+void recovery_rui_exit(void)
+{
+ rui_exit();
+
+ cleanup_screens();
+ free(rui_screens);
+ cleanup_menus();
+ free(rui_menus);
+ free(rui_screen_styles);
+ free(rui_menu_styles);
+ free(rui_ruler_styles);
+ free(rui_animations);
+ free(rui_images);
+ free(rui_colors);
+ cleanup_rulers();
+ free(rui_rulers);
+ free(rui_descriptions);
+
+ free(rui_config_labels.rui_screens);
+ free(rui_config_labels.rui_menus);
+ free(rui_config_labels.rui_screen_styles);
+ free(rui_config_labels.rui_menu_styles);
+ free(rui_config_labels.rui_ruler_styles);
+ free(rui_config_labels.rui_animations);
+ free(rui_config_labels.rui_images);
+ free(rui_config_labels.rui_colors);
+ free(rui_config_labels.rui_rulers);
+ free(rui_config_labels.rui_descriptions);
+
+ free(rui_default_action);
+}
+
+
+int recovery_gui(config_t *cfg)
+{
+#ifdef HAVE_TDM
+ /* These should be set externally */
+
+ /*
+ * Under normal circumstances XDG_RUNTIME_DIR is set during
+ * session setup (login). On initrd there is no session. This
+ * is used in libwayland-server and there is no default value.
+ */
+ setenv("XDG_RUNTIME_DIR", "/run", 1);
+
+ /* Tell TBM to work without an external wayland display manager. */
+ setenv("TBM_DISPLAY_SERVER", "1", 1);
+#endif
+
+ if (!recovery_rui_init(cfg)) {
+ LOGD("Can't initialize GUI.\n");
+ return 1;
+ }
+
+ rui_default_action = get_action_from_cmdline();
+ if (!rui_default_action)
+ rui_default_action = get_action_from_file();
+
+ if (rui_default_action) {
+ int idx = find_string(rui_config_labels.rui_action_handlers, rui_default_action);
+ if (idx < 0) {
+ LOGD("Invalid action: %s\n", rui_default_action);
+ free(rui_default_action);
+ rui_default_action = NULL;
+ } else
+ rui_default_handler = rui_action_handlers[idx];
+ }
+
+ if (!ev_init()) {
+ LOGD("Can't initialize input subsystem.\n");
+ recovery_rui_exit();
+ return 1;
+ }
+
+ rui_draw();
+
+ while (running)
+ if (!ev_dispatch(recovery_rui_input_callback))
+ break;
+
+ ev_exit();
+ recovery_rui_exit();
+
+ return 0;
+}
--- /dev/null
+This directory contains some source files for images used by system-recovery
+framebuffer GUI.
+
+The menu title image can be generated by ./make-menu-title.sh shell-script.
+The required font SamsungSans_Md.ttf can be found
+in magnolia/framework/graphics/all-fonts-slp project.
+
+It is possible to draw menu title by using fixed-width font but
+label typed with TrueType font looks better.
+
+To draw progress animation system-recovery uses interlaced PNG-image
+with all frames combined. For making tizen-anim.png you can use ./make-anim.sh
+shell-script which uses ./interlace-frames.py python-script.
--- /dev/null
+#!/usr/bin/python
+#
+# Copyright (C) 2014 The Android Open Source Project
+# Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Script to take a set of frames (PNG files) for a recovery animation
+and turn it into a single output image which contains the input frames
+interlaced by row. Run with the names of all the input frames on the
+command line, in order, followed by the name of the output file."""
+
+import sys
+try:
+ import Image
+ import PngImagePlugin
+except ImportError:
+ print "This script requires the Python Imaging Library to be installed."
+ sys.exit(1)
+
+frames = [Image.open(fn).convert("RGBA") for fn in sys.argv[1:-1]]
+assert len(frames) > 0, "Must have at least one input frame."
+sizes = set()
+for fr in frames:
+ sizes.add(fr.size)
+
+assert len(sizes) == 1, "All input images must have the same size."
+w, h = sizes.pop()
+N = len(frames)
+
+out = Image.new("RGBA", (w, h * N))
+for j in range(h):
+ for i in range(w):
+ for fn, f in enumerate(frames):
+ out.putpixel((i, j * N + fn), f.getpixel((i, j)))
+
+# When loading this image, the graphics library expects to find a text
+# chunk that specifies how many frames this animation represents. If
+# you post-process the output of this script with some kind of
+# optimizer tool (eg pngcrush or zopflipng) make sure that your
+# optimizer preserves this text chunk.
+
+meta = PngImagePlugin.PngInfo()
+meta.add_text("Frames", str(N))
+
+out.save(sys.argv[-1], pnginfo=meta)
--- /dev/null
+#!/bin/sh
+
+FNAME="../res/system-recovery/images/tizen-anim.png"
+SRCIMG="./tizen-anim?src.png"
+
+./interlace-frames.py $SRCIMG "$FNAME"
+optipng -o 7 "$FNAME"
--- /dev/null
+#!/bin/sh
+
+FNAME="../res/system-recovery/images/menu-title.png"
+TEXT="Tizen system recovery"
+FONTSIZE=46
+FONT="./SamsungSans_Md.ttf"
+
+convert -background black -fill white -font "$FONT" -pointsize $FONTSIZE label:"$TEXT" "$FNAME"
+
+optipng -o 7 "$FNAME"
--- /dev/null
+// -*- mode: conf; indent-tabs-mode: nil -*-
+
+m4_define(`confirm_action',`({
+ label = "Yes";
+ action_handler = "$1";
+ exit_after_action = $2;
+ },{
+ label = "No";
+ screen_switch_to = "BACK";
+ })')m4_dnl
+
+action_handlers = {
+ reboot = "reboot -f";
+ factory-reset = "touch -f /opt/.factoryreset";
+ safeboot = "touch -f /opt/etc/.safeboot";
+}
+
+headless_action = "factory-reset";
+
+colors = {
+ background = "#000000ff";
+ title = "#1bc7ccff";
+ ruler = "#1bc7ccff";
+ white = "#ffffffff";
+};
+
+ruler_styles = {
+ common = {
+ c_ruler = "ruler";
+ };
+};
+
+menu_styles = {
+ common = {
+ item_height = 80;
+ item_spacing = 8;
+ text_pos_x = 15;
+ c_bg_selected = "title";
+ c_bg_unselected = "background";
+ c_text_selected = "white";
+ c_text_unselected = "white";
+ };
+};
+
+screen_styles = {
+ common = {
+ c_background = "background";
+ };
+};
+
+description_styles = {
+ common = {
+ c_title = "title";
+ c_text = "white";
+ };
+};
+
+rulers = {
+ main = (
+ {
+ pos_x = 0;
+ pos_y = 80;
+ height = 2;
+ style = "common";
+ }, {
+ pos_x = 0;
+ pos_y = 420;
+ height = 2;
+ style = "common";
+ });
+
+ confirm = (
+ {
+ pos_x = 0;
+ pos_y = 80;
+ height = 2;
+ style = "common";
+ });
+};
+
+images = {
+ background_default = {
+ fname = "@SYSTEM_RECOVERY_IMAGE_DIR@/warning.png";
+ c_bg = "background"; // reference to colors
+ align_hor = "center";
+ align_ver = "bottom";
+ offset_x = 0;
+ offset_y = 0;
+ img_type = "alpha"; // alt: "no-alpha";
+ // surface = ;
+ };
+ menu_title = {
+ fname = "@SYSTEM_RECOVERY_IMAGE_DIR@/menu-title.png";
+ c_bg = "title";
+ align_hor = "center";
+ align_ver = "top";
+ offset_x = 0;
+ offset_y = 20;
+ img_type = "no-alpha"; // alt: "no-alpha";
+ // surface = ;
+ };
+};
+
+animations = {
+ working = {
+ fname = "@SYSTEM_RECOVERY_IMAGE_DIR@/tizen-anim.png";
+ c_bg = "background";
+ align_hor = "center";
+ align_ver = "middle";
+ offset_x = 0;
+ offset_y = 0;
+ frames_num = 0;
+ current_frame = 0;
+ img_type = "no-alpha"; // alt: "no-alpha";
+ // surface = ;
+ };
+};
+
+menus = {
+ main = {
+ pos_x = 0; // use M4 macros
+ pos_y = 100; // use M4 macros
+ style = "common";
+ // item_selected = ;
+ // item_default = ;
+ actions = ({
+ label = "Reboot system now";
+ screen_switch_to = "reboot";
+ // action_handler = ;
+ },{
+ label = "Safe mode";
+ screen_switch_to = "safe";
+ // action_handler = ;
+ },{
+ label = "Phone reinitialisation";
+ screen_switch_to = "factory";
+ // action_handler = ;
+ });
+ };
+ reboot = {
+ pos_x = 0; // use M4 macros
+ pos_y = 480; // use M4 macros
+ style = "common";
+ item_selected = 1;
+ item_default = 1;
+ actions = confirm_action(`reboot', 0);
+ };
+ safe = {
+ pos_x = 0; // use M4 macros
+ pos_y = 480; // use M4 macros
+ style = "common";
+ item_selected = 1;
+ item_default = 1;
+ actions = confirm_action(`safeboot', 1);
+ };
+ factory = {
+ pos_x = 0; // use M4 macros
+ pos_y = 480; // use M4 macros
+ style = "common";
+ item_selected = 1;
+ item_default = 1;
+ actions = ({
+ label = "Yes";
+ screen_switch_to = "factory-run";
+ action_handler = "factory-reset";
+ exit_after_action = 1;
+ },{
+ label = "No";
+ screen_switch_to = "BACK";
+ });
+ };
+};
+
+descriptions = {
+ main = {
+ pos_x = 15;
+ pos_y = 480;
+ style = "common";
+ title = "Controls:";
+ text = "Volume Up/Down to move menu cursor\n"
+ "Power button to select";
+ };
+
+ reboot = {
+ pos_x = 15;
+ pos_y = 100;
+ title = "The phone will be restarted.";
+ text = "Continue?";
+ style = "common";
+ };
+
+ safe = {
+ pos_x = 15;
+ pos_y = 100;
+ title = "Safe mode:",
+ text = "The phone will be started in safe mode.\n"
+ "Home screen will be changed to default\n"
+ "setting and just allow a user to use\n"
+ "only preloaded applications.\n"
+ "Continue?";
+ style = "common";
+ };
+
+ factory = {
+ pos_x = 15;
+ pos_y = 100;
+ title = "Factory reset (except SD-card)";
+ text = "This will erase all data from your\n"
+ "phone's internal storage, including\n"
+ "settings of downloaded and preloaded\n"
+ "applications and system configuration.\n"
+ "Continue?";
+ style = "common";
+ };
+
+ factory-run = {
+ pos_x = 15;
+ pos_y = 100;
+ style = "common";
+ title = "Restoring settings to factory default.";
+ text = "Please wait. Do not turn off.\n"
+ "(Hold power button for 3 seconds\n"
+ "to reboot the device. Not recommended.)";
+ }
+};
+
+screens = {
+ main = {
+ style = "common";
+ menu = "main";
+ rulers = "main";
+ description = "main";
+ // progress_bar = ;
+ images = ("background_default", "menu_title");
+ // animations = ;
+ // on_enter = ;
+ // draw = ;
+ screen_back = "CURRENT";
+ };
+ reboot = {
+ style = "common";
+ menu = "reboot";
+ description = "reboot"
+ rulers = "confirm" ;
+ // progress_bar = ;
+ images = ("background_default", "menu_title");
+ // animations = ;
+ // on_enter = ;
+ // draw = ;
+ screen_back = "main";
+ };
+ safe = {
+ style = "common";
+ menu = "safe";
+ description = "safe";
+ rulers = "confirm";
+ // progress_bar = ;
+ images = ("background_default", "menu_title");
+ // animations = ;
+ // on_enter = ;
+ // draw = ;
+ screen_back = "main";
+ };
+ factory = {
+ style = "common";
+ menu = "factory";
+ description = "factory";
+ rulers = "confirm";
+ // progress_bar = ;
+ images = ("background_default", "menu_title");
+ // animations = ;
+ // on_enter = ;
+ // draw = ;
+ screen_back = "main";
+ };
+ factory-run = {
+ style = "common";
+ description = "factory-run";
+ rulers = "confirm";
+ images = ("background_default", "menu_title");
+ animations = ("working");
+ screen_back = "main";
+ allow_force_reboot = 1;
+ };
+};
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <libconfig.h>
+#include <stdio.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LOGD printf
+#define FILE_IO_BUF_SIZE 128
+
+#define ROOT_MOUNT_DIR "/system"
+#define INITRD_MOUNT_DIR "/system/mnt/initrd-recovery"
+
+int pivot_root(const char *new_root, const char *put_old);
+
+void sys_power_reboot(void);
+
+int recovery_gui(config_t *cfg);
+int recovery_headless(config_t *cfg);
+char *get_action_from_cmdline(void);
+char *get_action_from_file(void);
+
+#ifdef __cplusplus
+}
+#endif