Initial source 48/178848/1
authorKichan Kwon <k_c.kwon@samsung.com>
Mon, 14 May 2018 08:14:09 +0000 (17:14 +0900)
committerKichan Kwon <k_c.kwon@samsung.com>
Mon, 14 May 2018 08:37:35 +0000 (17:37 +0900)
Change-Id: I22b9a4f8d1082d85290ddc51c50bd816e433d98e
Signed-off-by: Kichan Kwon <k_c.kwon@samsung.com>
64 files changed:
.gitignore [new file with mode: 0644]
LICENSE [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
autogen.sh [new file with mode: 0755]
configure.ac [new file with mode: 0644]
packaging/system-recovery.manifest [new file with mode: 0644]
packaging/system-recovery.spec [new file with mode: 0644]
src/fonts/font-10x18.h [new file with mode: 0644]
src/librui/common.h [new file with mode: 0644]
src/librui/fbdev.h [new file with mode: 0644]
src/librui/graphics-fbdev-common.c [new file with mode: 0644]
src/librui/graphics-fbdev.c [new file with mode: 0644]
src/librui/graphics-tdm.c [new file with mode: 0644]
src/librui/graphics.c [new file with mode: 0644]
src/librui/graphics.h [new file with mode: 0644]
src/librui/input-events.c [new file with mode: 0644]
src/librui/input-events.h [new file with mode: 0644]
src/librui/resources.c [new file with mode: 0644]
src/librui/rui-description.c [new file with mode: 0644]
src/librui/rui-description.h [new file with mode: 0644]
src/librui/rui-image.h [new file with mode: 0644]
src/librui/rui-images.c [new file with mode: 0644]
src/librui/rui-menu.c [new file with mode: 0644]
src/librui/rui-menu.h [new file with mode: 0644]
src/librui/rui-progress-bar.c [new file with mode: 0644]
src/librui/rui-progress-bar.h [new file with mode: 0644]
src/librui/rui-ruler.h [new file with mode: 0644]
src/librui/rui-rulers.c [new file with mode: 0644]
src/librui/rui.c [new file with mode: 0644]
src/librui/rui.h [new file with mode: 0644]
src/librui/tdm-if.c [new file with mode: 0755]
src/librui/tdm-if.h [new file with mode: 0755]
src/shared/log.c [new file with mode: 0644]
src/shared/log.h [new file with mode: 0644]
src/system-recovery/.gitignore [new file with mode: 0644]
src/system-recovery/50-system-recovery-sprd.list [new file with mode: 0644]
src/system-recovery/50-system-recovery.list.m4.in [new file with mode: 0644]
src/system-recovery/process-util.c [new file with mode: 0644]
src/system-recovery/process-util.h [new file with mode: 0644]
src/system-recovery/recovery-action-set.in [new file with mode: 0755]
src/system-recovery/recovery-headless.c [new file with mode: 0644]
src/system-recovery/recovery-init.in [new file with mode: 0644]
src/system-recovery/recovery-main.c [new file with mode: 0644]
src/system-recovery/recovery-rui-skin.h [new file with mode: 0644]
src/system-recovery/recovery-rui.c [new file with mode: 0644]
src/system-recovery/res-util/README.txt [new file with mode: 0644]
src/system-recovery/res-util/interlace-frames.py [new file with mode: 0755]
src/system-recovery/res-util/make-anim.sh [new file with mode: 0755]
src/system-recovery/res-util/make-menu-title.sh [new file with mode: 0755]
src/system-recovery/res-util/tizen-anim1src.png [new file with mode: 0644]
src/system-recovery/res-util/tizen-anim2src.png [new file with mode: 0644]
src/system-recovery/res-util/tizen-anim3src.png [new file with mode: 0644]
src/system-recovery/res-util/tizen-anim4src.png [new file with mode: 0644]
src/system-recovery/res-util/tizen-anim5src.png [new file with mode: 0644]
src/system-recovery/res/images/12x22.png [new file with mode: 0644]
src/system-recovery/res/images/18x32.png [new file with mode: 0644]
src/system-recovery/res/images/font.png [new file with mode: 0644]
src/system-recovery/res/images/menu-title-480x800.png [new file with mode: 0644]
src/system-recovery/res/images/menu-title-720x1280.png [new file with mode: 0644]
src/system-recovery/res/images/menu-title.png [new file with mode: 0644]
src/system-recovery/res/images/tizen-anim.png [new file with mode: 0644]
src/system-recovery/res/images/warning.png [new file with mode: 0644]
src/system-recovery/system-recovery.cfg.m4.in [new file with mode: 0644]
src/system-recovery/system-recovery.h [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..5cf9594
--- /dev/null
@@ -0,0 +1,19 @@
+*.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
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..9fe66f6
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,203 @@
+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.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..20f3675
--- /dev/null
@@ -0,0 +1,195 @@
+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)
diff --git a/autogen.sh b/autogen.sh
new file mode 100755 (executable)
index 0000000..968bc8e
--- /dev/null
@@ -0,0 +1,21 @@
+#!/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 $?
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..23f1b2c
--- /dev/null
@@ -0,0 +1,153 @@
+#                                               -*- 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}
+])
diff --git a/packaging/system-recovery.manifest b/packaging/system-recovery.manifest
new file mode 100644 (file)
index 0000000..2a0cec5
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+  <request>
+    <domain name="_"/>
+  </request>
+</manifest>
diff --git a/packaging/system-recovery.spec b/packaging/system-recovery.spec
new file mode 100644 (file)
index 0000000..4742d1e
--- /dev/null
@@ -0,0 +1,116 @@
+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
diff --git a/src/fonts/font-10x18.h b/src/fonts/font-10x18.h
new file mode 100644 (file)
index 0000000..1b3d86f
--- /dev/null
@@ -0,0 +1,216 @@
+/*-*- 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,
+       }
+};
diff --git a/src/librui/common.h b/src/librui/common.h
new file mode 100644 (file)
index 0000000..72ce978
--- /dev/null
@@ -0,0 +1,49 @@
+/*-*- 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
diff --git a/src/librui/fbdev.h b/src/librui/fbdev.h
new file mode 100644 (file)
index 0000000..2949820
--- /dev/null
@@ -0,0 +1,46 @@
+/*-*- 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
diff --git a/src/librui/graphics-fbdev-common.c b/src/librui/graphics-fbdev-common.c
new file mode 100644 (file)
index 0000000..4e23054
--- /dev/null
@@ -0,0 +1,87 @@
+/*-*- 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;
+}
diff --git a/src/librui/graphics-fbdev.c b/src/librui/graphics-fbdev.c
new file mode 100644 (file)
index 0000000..c0211c9
--- /dev/null
@@ -0,0 +1,157 @@
+/*-*- 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);
+}
diff --git a/src/librui/graphics-tdm.c b/src/librui/graphics-tdm.c
new file mode 100644 (file)
index 0000000..0cbe536
--- /dev/null
@@ -0,0 +1,101 @@
+/* -*- 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;
+}
diff --git a/src/librui/graphics.c b/src/librui/graphics.c
new file mode 100644 (file)
index 0000000..f564ab5
--- /dev/null
@@ -0,0 +1,495 @@
+/*-*- 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;
+}
diff --git a/src/librui/graphics.h b/src/librui/graphics.h
new file mode 100644 (file)
index 0000000..a768462
--- /dev/null
@@ -0,0 +1,155 @@
+/*-*- 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
diff --git a/src/librui/input-events.c b/src/librui/input-events.c
new file mode 100644 (file)
index 0000000..325391c
--- /dev/null
@@ -0,0 +1,309 @@
+/*-*- 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;
+}
diff --git a/src/librui/input-events.h b/src/librui/input-events.h
new file mode 100644 (file)
index 0000000..b07f996
--- /dev/null
@@ -0,0 +1,59 @@
+/*-*- 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
diff --git a/src/librui/resources.c b/src/librui/resources.c
new file mode 100644 (file)
index 0000000..cd579f4
--- /dev/null
@@ -0,0 +1,534 @@
+/*-*- 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);
+}
diff --git a/src/librui/rui-description.c b/src/librui/rui-description.c
new file mode 100644 (file)
index 0000000..c906499
--- /dev/null
@@ -0,0 +1,32 @@
+/*-*- 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);
+}
diff --git a/src/librui/rui-description.h b/src/librui/rui-description.h
new file mode 100644 (file)
index 0000000..293ac3c
--- /dev/null
@@ -0,0 +1,44 @@
+/*-*- 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
diff --git a/src/librui/rui-image.h b/src/librui/rui-image.h
new file mode 100644 (file)
index 0000000..bd7408f
--- /dev/null
@@ -0,0 +1,67 @@
+/*-*- 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
diff --git a/src/librui/rui-images.c b/src/librui/rui-images.c
new file mode 100644 (file)
index 0000000..b5b0998
--- /dev/null
@@ -0,0 +1,153 @@
+/*-*- 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;
+}
diff --git a/src/librui/rui-menu.c b/src/librui/rui-menu.c
new file mode 100644 (file)
index 0000000..fb7698f
--- /dev/null
@@ -0,0 +1,106 @@
+/*-*- 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;
+}
diff --git a/src/librui/rui-menu.h b/src/librui/rui-menu.h
new file mode 100644 (file)
index 0000000..1bb051a
--- /dev/null
@@ -0,0 +1,68 @@
+/*-*- 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
diff --git a/src/librui/rui-progress-bar.c b/src/librui/rui-progress-bar.c
new file mode 100644 (file)
index 0000000..80fbfdb
--- /dev/null
@@ -0,0 +1,68 @@
+/*-*- 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;
+}
diff --git a/src/librui/rui-progress-bar.h b/src/librui/rui-progress-bar.h
new file mode 100644 (file)
index 0000000..def59f8
--- /dev/null
@@ -0,0 +1,48 @@
+/*-*- 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
diff --git a/src/librui/rui-ruler.h b/src/librui/rui-ruler.h
new file mode 100644 (file)
index 0000000..1c4aa09
--- /dev/null
@@ -0,0 +1,42 @@
+/*-*- 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
diff --git a/src/librui/rui-rulers.c b/src/librui/rui-rulers.c
new file mode 100644 (file)
index 0000000..2f67995
--- /dev/null
@@ -0,0 +1,36 @@
+/*-*- 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++;
+       }
+}
diff --git a/src/librui/rui.c b/src/librui/rui.c
new file mode 100644 (file)
index 0000000..0954853
--- /dev/null
@@ -0,0 +1,119 @@
+/*-*- 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();
+}
diff --git a/src/librui/rui.h b/src/librui/rui.h
new file mode 100644 (file)
index 0000000..765092b
--- /dev/null
@@ -0,0 +1,72 @@
+/*-*- 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
diff --git a/src/librui/tdm-if.c b/src/librui/tdm-if.c
new file mode 100755 (executable)
index 0000000..7f2371b
--- /dev/null
@@ -0,0 +1,360 @@
+/* -*- 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);
+}
diff --git a/src/librui/tdm-if.h b/src/librui/tdm-if.h
new file mode 100755 (executable)
index 0000000..9c92e7d
--- /dev/null
@@ -0,0 +1,69 @@
+/* -*- 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__ */
diff --git a/src/shared/log.c b/src/shared/log.c
new file mode 100644 (file)
index 0000000..fd08409
--- /dev/null
@@ -0,0 +1,414 @@
+/*-*- 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;
+}
diff --git a/src/shared/log.h b/src/shared/log.h
new file mode 100644 (file)
index 0000000..ce26b1e
--- /dev/null
@@ -0,0 +1,71 @@
+/*-*- 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)
diff --git a/src/system-recovery/.gitignore b/src/system-recovery/.gitignore
new file mode 100644 (file)
index 0000000..9cda7ea
--- /dev/null
@@ -0,0 +1,2 @@
+/50-system-recovery.list
+/recovery-init
\ No newline at end of file
diff --git a/src/system-recovery/50-system-recovery-sprd.list b/src/system-recovery/50-system-recovery-sprd.list
new file mode 100644 (file)
index 0000000..6b30709
--- /dev/null
@@ -0,0 +1,24 @@
+# ---- 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
+"
diff --git a/src/system-recovery/50-system-recovery.list.m4.in b/src/system-recovery/50-system-recovery.list.m4.in
new file mode 100644 (file)
index 0000000..a8e3344
--- /dev/null
@@ -0,0 +1,44 @@
+# ---- 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
+"
diff --git a/src/system-recovery/process-util.c b/src/system-recovery/process-util.c
new file mode 100644 (file)
index 0000000..a5a34b9
--- /dev/null
@@ -0,0 +1,90 @@
+/*-*- 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;
+}
diff --git a/src/system-recovery/process-util.h b/src/system-recovery/process-util.h
new file mode 100644 (file)
index 0000000..016c51a
--- /dev/null
@@ -0,0 +1,34 @@
+/*-*- 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
diff --git a/src/system-recovery/recovery-action-set.in b/src/system-recovery/recovery-action-set.in
new file mode 100755 (executable)
index 0000000..a6ddf8c
--- /dev/null
@@ -0,0 +1,18 @@
+#!/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."
diff --git a/src/system-recovery/recovery-headless.c b/src/system-recovery/recovery-headless.c
new file mode 100644 (file)
index 0000000..e07035c
--- /dev/null
@@ -0,0 +1,68 @@
+/*-*- 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);
+}
diff --git a/src/system-recovery/recovery-init.in b/src/system-recovery/recovery-init.in
new file mode 100644 (file)
index 0000000..bdf5338
--- /dev/null
@@ -0,0 +1,79 @@
+#!/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
diff --git a/src/system-recovery/recovery-main.c b/src/system-recovery/recovery-main.c
new file mode 100644 (file)
index 0000000..dd30ce9
--- /dev/null
@@ -0,0 +1,125 @@
+/*-*- 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;
+}
diff --git a/src/system-recovery/recovery-rui-skin.h b/src/system-recovery/recovery-rui-skin.h
new file mode 100644 (file)
index 0000000..fe2df56
--- /dev/null
@@ -0,0 +1,136 @@
+/*-*- 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
diff --git a/src/system-recovery/recovery-rui.c b/src/system-recovery/recovery-rui.c
new file mode 100644 (file)
index 0000000..0deefad
--- /dev/null
@@ -0,0 +1,854 @@
+/*-*- 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;
+}
diff --git a/src/system-recovery/res-util/README.txt b/src/system-recovery/res-util/README.txt
new file mode 100644 (file)
index 0000000..e79d127
--- /dev/null
@@ -0,0 +1,13 @@
+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.
diff --git a/src/system-recovery/res-util/interlace-frames.py b/src/system-recovery/res-util/interlace-frames.py
new file mode 100755 (executable)
index 0000000..d8b11df
--- /dev/null
@@ -0,0 +1,56 @@
+#!/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)
diff --git a/src/system-recovery/res-util/make-anim.sh b/src/system-recovery/res-util/make-anim.sh
new file mode 100755 (executable)
index 0000000..a169dbe
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+FNAME="../res/system-recovery/images/tizen-anim.png"
+SRCIMG="./tizen-anim?src.png"
+
+./interlace-frames.py $SRCIMG "$FNAME"
+optipng -o 7 "$FNAME"
diff --git a/src/system-recovery/res-util/make-menu-title.sh b/src/system-recovery/res-util/make-menu-title.sh
new file mode 100755 (executable)
index 0000000..5c194cb
--- /dev/null
@@ -0,0 +1,10 @@
+#!/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"
diff --git a/src/system-recovery/res-util/tizen-anim1src.png b/src/system-recovery/res-util/tizen-anim1src.png
new file mode 100644 (file)
index 0000000..54995eb
Binary files /dev/null and b/src/system-recovery/res-util/tizen-anim1src.png differ
diff --git a/src/system-recovery/res-util/tizen-anim2src.png b/src/system-recovery/res-util/tizen-anim2src.png
new file mode 100644 (file)
index 0000000..43533a3
Binary files /dev/null and b/src/system-recovery/res-util/tizen-anim2src.png differ
diff --git a/src/system-recovery/res-util/tizen-anim3src.png b/src/system-recovery/res-util/tizen-anim3src.png
new file mode 100644 (file)
index 0000000..e949873
Binary files /dev/null and b/src/system-recovery/res-util/tizen-anim3src.png differ
diff --git a/src/system-recovery/res-util/tizen-anim4src.png b/src/system-recovery/res-util/tizen-anim4src.png
new file mode 100644 (file)
index 0000000..bcd8c35
Binary files /dev/null and b/src/system-recovery/res-util/tizen-anim4src.png differ
diff --git a/src/system-recovery/res-util/tizen-anim5src.png b/src/system-recovery/res-util/tizen-anim5src.png
new file mode 100644 (file)
index 0000000..cb07923
Binary files /dev/null and b/src/system-recovery/res-util/tizen-anim5src.png differ
diff --git a/src/system-recovery/res/images/12x22.png b/src/system-recovery/res/images/12x22.png
new file mode 100644 (file)
index 0000000..f63dc89
Binary files /dev/null and b/src/system-recovery/res/images/12x22.png differ
diff --git a/src/system-recovery/res/images/18x32.png b/src/system-recovery/res/images/18x32.png
new file mode 100644 (file)
index 0000000..aa7064e
Binary files /dev/null and b/src/system-recovery/res/images/18x32.png differ
diff --git a/src/system-recovery/res/images/font.png b/src/system-recovery/res/images/font.png
new file mode 100644 (file)
index 0000000..f63dc89
Binary files /dev/null and b/src/system-recovery/res/images/font.png differ
diff --git a/src/system-recovery/res/images/menu-title-480x800.png b/src/system-recovery/res/images/menu-title-480x800.png
new file mode 100644 (file)
index 0000000..213c766
Binary files /dev/null and b/src/system-recovery/res/images/menu-title-480x800.png differ
diff --git a/src/system-recovery/res/images/menu-title-720x1280.png b/src/system-recovery/res/images/menu-title-720x1280.png
new file mode 100644 (file)
index 0000000..ef8aaff
Binary files /dev/null and b/src/system-recovery/res/images/menu-title-720x1280.png differ
diff --git a/src/system-recovery/res/images/menu-title.png b/src/system-recovery/res/images/menu-title.png
new file mode 100644 (file)
index 0000000..213c766
Binary files /dev/null and b/src/system-recovery/res/images/menu-title.png differ
diff --git a/src/system-recovery/res/images/tizen-anim.png b/src/system-recovery/res/images/tizen-anim.png
new file mode 100644 (file)
index 0000000..a2e8f0b
Binary files /dev/null and b/src/system-recovery/res/images/tizen-anim.png differ
diff --git a/src/system-recovery/res/images/warning.png b/src/system-recovery/res/images/warning.png
new file mode 100644 (file)
index 0000000..d591696
Binary files /dev/null and b/src/system-recovery/res/images/warning.png differ
diff --git a/src/system-recovery/system-recovery.cfg.m4.in b/src/system-recovery/system-recovery.cfg.m4.in
new file mode 100644 (file)
index 0000000..664c272
--- /dev/null
@@ -0,0 +1,285 @@
+// -*- 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;
+    };
+};
diff --git a/src/system-recovery/system-recovery.h b/src/system-recovery/system-recovery.h
new file mode 100644 (file)
index 0000000..b75ade8
--- /dev/null
@@ -0,0 +1,46 @@
+/*-*- 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