Upload initial codes 07/132907/2
authorKunhoon Baik <knhoon.baik@samsung.com>
Thu, 8 Jun 2017 08:29:30 +0000 (17:29 +0900)
committerKunhoon Baik <knhoon.baik@samsung.com>
Thu, 8 Jun 2017 08:33:26 +0000 (17:33 +0900)
Copied & Modified initial codes of initrd-recovery from reference repository

Change-Id: I9dc5af97ddf356b96e21fa73e5f375bafacf333c

62 files changed:
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/initrd-recovery.manifest [new file with mode: 0644]
packaging/initrd-recovery.spec [new file with mode: 0644]
src/fonts/font-10x18.h [new file with mode: 0644]
src/initrd-recovery/00-initrd-recovery.list [new file with mode: 0644]
src/initrd-recovery/init [new file with mode: 0755]
src/initrd-recovery/mkinitrd-recovery.sh [new file with mode: 0755]
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.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/minireboot/minireboot.c [new file with mode: 0644]
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.list.m4 [new file with mode: 0644]
src/system-recovery/minvconf.c [new file with mode: 0644]
src/system-recovery/minvconf.h [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-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.h [new file with mode: 0644]

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..68feca2
--- /dev/null
@@ -0,0 +1,181 @@
+ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
+
+SUBDIRS = .
+
+initrd_recovery_libexecdir=$(prefix)/lib/initrd-recovery
+initrd_recovery_sharedir=$(prefix)/share/initrd-recovery
+initrd_recovery_install_dropindir=$(initrd_recovery_sharedir)/initrd.list.d
+
+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_libexec_PROGRAMS =
+initrd_recovery_libexec_SCRIPTS =
+
+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)
+
+# ------------------------------------------------------------------------------
+initrd_recovery_libexec_SCRIPTS += \
+       src/initrd-recovery/init \
+       src/initrd-recovery/mkinitrd-recovery.sh
+
+initrd_recovery_install_dropin_DATA += \
+       src/initrd-recovery/00-initrd-recovery.list
+
+# ------------------------------------------------------------------------------
+minireboot_SOURCES = \
+       src/minireboot/minireboot.c
+
+minireboot_CFLAGS = \
+       $(AM_CFLAGS)
+
+minireboot_LDADD = \
+       $(AM_LIBS)
+
+initrd_recovery_libexec_PROGRAMS += \
+       minireboot
+
+# ------------------------------------------------------------------------------
+if RECOVERY_GUI
+noinst_LTLIBRARIES += \
+       librui.la
+
+librui_la_SOURCES = \
+       src/librui/graphics-fbdev-common.c \
+       src/librui/graphics-fbdev.c \
+       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
+
+librui_la_CFLAGS = \
+       $(LIBPNG_CFLAGS) \
+       $(VCONF_INTERNAL_KEYS) \
+       $(AM_CFLAGS) \
+       -I src/librui \
+       -I src/fonts
+
+librui_la_LIBADD = \
+       $(LIBPNG_LIBS) \
+       $(AM_LIBS)
+endif
+
+# ------------------------------------------------------------------------------
+system_recovery_libexecdir = \
+       $(prefix)/lib/system-recovery
+
+if RECOVERY_GUI
+system_recovery_resdir = \
+       $(system_recovery_libexecdir)/res
+
+system_recovery_res_imagedir = \
+       $(system_recovery_resdir)/images
+
+system_recovery_SOURCES = \
+       src/system-recovery/process-util.c \
+       src/system-recovery/minvconf.c \
+       src/system-recovery/recovery-main.c \
+       src/system-recovery/recovery-rui.c
+
+system_recovery_CFLAGS = \
+       $(AM_CFLAGS) \
+       -I $(librui_la_CFLAGS) \
+       -I src/system-recovery
+
+system_recovery_LDADD = \
+       $(AM_LIBS) \
+       librui.la
+
+system_recovery_libexec_PROGRAMS = \
+       system-recovery
+
+system_recovery_res_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
+endif
+
+system_recovery_libexec_SCRIPTS = \
+       src/system-recovery/recovery-init
+
+initrd_recovery_install_dropin_DATA += \
+       src/system-recovery/50-system-recovery.list
+
+EXTRA_DIST += \
+       src/system-recovery/recovery-init.in \
+       src/system-recovery/50-system-recovery.list.m4
+
+CLEANFILES += \
+       src/system-recovery/recovery-init \
+       src/system-recovery/50-system-recovery.list
+
+# ------------------------------------------------------------------------------
+substitutions = \
+       '|PACKAGE_VERSION=$(PACKAGE_VERSION)|' \
+       '|PACKAGE_NAME=$(PACKAGE_NAME)|' \
+       '|PACKAGE_URL=$(PACKAGE_URL)|' \
+       '|includedir=$(includedir)|' \
+       '|VERSION=$(VERSION)|' \
+       '|MKDIR_P=$(MKDIR_P)|' \
+       '|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..f13d339
--- /dev/null
@@ -0,0 +1,100 @@
+#                                               -*- 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_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_AWK
+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_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)
+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(LIBSYSTEM, [libsystem])
+       PKG_CHECK_MODULES(LIBPNG, [libpng])
+       PKG_CHECK_MODULES(VCONF_INTERNAL_KEYS, [vconf-internal-keys])
+fi
+
+AC_SUBST([RECOVERY_GUI], ["GUI"])
+AM_CONDITIONAL([RECOVERY_GUI], [test "x$enable_recovery_gui" != "xno"])
+
+# ------------------------------------------------------------------------------
+AC_SUBST(M4_DEFINES)
+
+# ------------------------------------------------------------------------------
+AC_CONFIG_FILES([Makefile])
+
+AC_OUTPUT
+AC_MSG_RESULT([
+        $PACKAGE_NAME $VERSION
+
+        prefix:                  ${prefix}
+
+        recovery gui mode:       ${enable_recovery_gui}
+
+        OUR CFLAGS:              ${OUR_CFLAGS} ${CFLAGS}
+])
diff --git a/packaging/initrd-recovery.manifest b/packaging/initrd-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/initrd-recovery.spec b/packaging/initrd-recovery.spec
new file mode 100644 (file)
index 0000000..45693c3
--- /dev/null
@@ -0,0 +1,81 @@
+Name:           initrd-recovery
+Summary:        Tools for system recovery
+Version:        0.1.0
+Release:        1
+Group:          System/Utilities
+License:        Apache-2.0
+ExclusiveArch:  %{arm}
+
+Source0:        %{name}-%{version}.tar.gz
+Source1001:     initrd-recovery.manifest
+
+BuildRequires:  autoconf
+BuildRequires:  automake
+BuildRequires:  libtool
+BuildRequires:  pkgconfig(libsystem)
+
+Requires:       system-recovery
+
+%description
+This is a special booting mode and executes system recovery mode on user
+selection like safe mode or phone initialization.
+
+%package -n system-recovery
+Summary:        System recovery
+Group:          System/Utilities
+License:        Apache-2.0
+
+#!BuildIgnore:  linux-glibc-devel
+#!BuildIgnore:  kernel-headers
+BuildRequires:  kernel-headers-tizen-dev
+BuildRequires:  pkgconfig(libpng)
+BuildRequires:  pkgconfig(vconf)
+BuildRequires:  pkgconfig(vconf-internal-keys)
+BuildRequires:  pkgconfig(libsystem)
+
+%description -n system-recovery
+A simple initrd menu for system recovery.
+
+%prep
+%setup -q
+
+%build
+cp %{SOURCE1001} .
+
+%define profile
+
+./autogen.sh
+%configure \
+%if ("%{?profile}" != "mobile")
+        --disable-recovery-gui \
+%endif
+
+make %{?_smp_mflags}
+
+%install
+mkdir -p %{buildroot}%{_datadir}/license
+cp -f LICENSE %{buildroot}%{_datadir}/license/initrd-recovery
+
+%make_install
+
+%posttrans
+%{_libdir}/initrd-recovery/mkinitrd-recovery.sh
+
+%files
+%defattr(-,root,root,-)
+%manifest initrd-recovery.manifest
+%{_datadir}/license/initrd-recovery
+%{_libdir}/initrd-recovery/init
+%{_libdir}/initrd-recovery/mkinitrd-recovery.sh
+%{_libdir}/initrd-recovery/minireboot
+%{_datadir}/initrd-recovery/initrd.list.d/00-initrd-recovery.list
+
+%files -n system-recovery
+%defattr(-,root,root,-)
+%manifest initrd-recovery.manifest
+%{_libdir}/system-recovery/recovery-init
+%{_datadir}/initrd-recovery/initrd.list.d/50-system-recovery.list
+%if ("%{?profile}" == "mobile")
+%{_libdir}/system-recovery/system-recovery
+%{_libdir}/system-recovery/res/images/*.png
+%endif
diff --git a/src/fonts/font-10x18.h b/src/fonts/font-10x18.h
new file mode 100644 (file)
index 0000000..b99cdf2
--- /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/initrd-recovery/00-initrd-recovery.list b/src/initrd-recovery/00-initrd-recovery.list
new file mode 100644 (file)
index 0000000..9b8618d
--- /dev/null
@@ -0,0 +1,30 @@
+# ---- Target contents ----------------------------------------------------- #
+VERBATIMS="
+/usr/lib/initrd-recovery/init
+"
+
+WITHLIBS="
+/usr/bin/bash
+/usr/bin/cat
+/usr/bin/cut
+/usr/bin/echo
+/usr/bin/gawk
+/usr/bin/grep
+/usr/bin/mkdir
+/usr/bin/mount
+/usr/bin/sleep
+/usr/bin/sync
+/usr/bin/tr
+/usr/bin/umount
+/usr/lib/initrd-recovery/minireboot
+/usr/sbin/partx
+"
+
+# LinkFileName:Target
+SYMLINKS="
+/bin/sh:bash
+/usr/bin/awk:/bin/gawk
+/sbin/init:/usr/lib/initrd-recovery/init
+/sbin/minireboot:/usr/lib/initrd-recovery/minireboot
+/sbin/reboot:/usr/lib/initrd-recovery/minireboot
+"
diff --git a/src/initrd-recovery/init b/src/initrd-recovery/init
new file mode 100755 (executable)
index 0000000..85367ab
--- /dev/null
@@ -0,0 +1,95 @@
+#!/bin/bash
+
+FAKE_ROOT=/system
+FAKE_ROOT_RO=/system-ro
+
+STATUS_DIR=${FAKE_ROOT}/opt/data/recovery
+STATUS_FILE=${STATUS_DIR}/RW.STATUS
+DELTA_PATH_FILE=${STATUS_DIR}/DELTA.PATH
+
+CAT="/bin/cat"
+SYNC="/bin/sync"
+MKDIR="/bin/mkdir"
+MOUNT="/bin/mount"
+UMOUNT="/bin/umount"
+GREP="/bin/grep"
+REBOOT="/sbin/reboot"
+AWK="/usr/bin/awk"
+CUT="/usr/bin/cut"
+TR="/usr/bin/tr"
+PARTX="/usr/sbin/partx"
+
+#------------------------------------------------
+#       get partition id
+#------------------------------------------------
+get_partition_id() {
+    EMMC_DEVICE="/dev/mmcblk0"
+    RET_PARTX=$("$PARTX" -s ${EMMC_DEVICE})
+    PART_ROOTFS=${EMMC_DEVICE}p$(IFS=; echo $RET_PARTX | "$AWK" 'tolower($6) == "rootfs" {print $1}')
+    PART_SYSTEM_DATA=${EMMC_DEVICE}p$(IFS=; echo $RET_PARTX | "$AWK" 'tolower($6) == "system-data" {print $1}')
+    PART_USER=${EMMC_DEVICE}p$(IFS=; echo $RET_PARTX | "$AWK" 'tolower($6) == "user" {print $1}')
+    PART_CSC=${EMMC_DEVICE}p$(IFS=; echo $RET_PARTX | "$AWK" 'tolower($6) == "csc" {print $1}')
+    PART_MODULES=${EMMC_DEVICE}p$(IFS=; echo $RET_PARTX | "$AWK" 'tolower($6) == "module" {print $1}')
+}
+
+#------------------------------------------------
+#       mount_blk_partitions
+#------------------------------------------------
+mount_blk_partitions() {
+    get_partition_id
+
+    echo "mount block device partitions"
+    "$MOUNT" -t ext4 ${PART_ROOTFS} ${FAKE_ROOT}
+    "$MOUNT" -t ext4 ${PART_SYSTEM_DATA} ${FAKE_ROOT}/opt
+    "$MOUNT" -t ext4 ${PART_USER} ${FAKE_ROOT}/opt/usr
+    "$MOUNT" -t ext4 ${PART_CSC} ${FAKE_ROOT}/opt/system/csc
+}
+
+#------------------------------------------------
+#       mount_partitions
+#------------------------------------------------
+mount_partitions() {
+    "$MOUNT" -t proc none /proc
+    "$MOUNT" -t sysfs none /sys
+    "$MOUNT" -t smackfs smackfs /smack
+    "$MOUNT" -t tmpfs tmpfs /run -o rw,nosuid,nodev,mode=755
+    "$MOUNT" -t tmpfs tmpfs /tmp -o mode=1777,smackfsroot=*
+
+    "$MKDIR" /dev/pts
+    "$MOUNT" -t devpts devpts /dev/pts
+}
+
+#------------------------------------------------
+#       do_reboot
+#------------------------------------------------
+do_reboot() {
+    echo "Reboot"
+    "$SYNC"
+    "$REBOOT"
+    while [ 1 ]
+    do
+        sleep 1
+        echo "."
+    done
+}
+
+#------------------------------------------------
+#       Main Routine Start
+#------------------------------------------------
+echo "You entered into /sbin/init on initrd"
+
+mount_partitions
+
+"$CAT" /proc/cmdline
+
+cd /
+
+BOOT_MODE=$("$CAT" /proc/cmdline | "$TR" ' ' \\n | "$GREP" bootmode | "$CUT" -d= -f2)
+
+if [ "z$BOOT_MODE" == "z" ]; then
+    echo "BOOT_MODE was NOT defined!!"
+    echo "Do reboot!!"
+    do_reboot
+fi
+echo "BOOTMODE is ${BOOT_MODE}"
+exec /sbin/${BOOT_MODE}-init
diff --git a/src/initrd-recovery/mkinitrd-recovery.sh b/src/initrd-recovery/mkinitrd-recovery.sh
new file mode 100755 (executable)
index 0000000..2042231
--- /dev/null
@@ -0,0 +1,272 @@
+#!/bin/sh
+
+CP="/bin/cp"
+LN="/bin/ln"
+SED="/bin/sed"
+MKDIR="/bin/mkdir"
+AWK="/usr/bin/awk"
+PARTX="/usr/sbin/partx"
+DIRNAME="/usr/bin/dirname"
+MKDIR="/bin/mkdir"
+LD_LINUX="/lib/ld-linux.so.3"
+
+INITRD_ROOT="/mnt/initrd-recovery"
+
+OBJECTS_SPECIFY_DIR="/usr/share/initrd-recovery/initrd.list.d"
+OBJECTS_DIRECTORY=
+OBJECTS_VERBATIM=
+OBJECTS_WITHLIB=
+OBJECTS_LIBONLY=
+OBJECTS_SYMLINK=
+
+BASE_DIRECTORIES="
+/dev
+/etc
+/proc
+/sdcard
+/smack
+/sys
+/system
+/system-ro
+/run
+/tmp
+/usr/bin
+/usr/sbin
+/usr/lib
+/var/log
+"
+
+BASE_DIR_SYMLINKS="
+/bin:usr/bin
+/sbin:usr/sbin
+/lib:usr/lib
+/opt:system/opt
+"
+
+OPT="default"
+
+#-----------------------------------------------------------------------------
+#       help
+#-----------------------------------------------------------------------------
+show_help() {
+    echo
+    echo "usage: `basename $0` [OPTION]"
+    echo "make initrd image"
+    echo
+    echo "  -h, --help          show help"
+    echo "  -p, --post          find initrd partition and format and make"
+    echo "                       initrd image to there"
+    echo
+}
+
+#-----------------------------------------------------------------------------
+#       find initrd-recovery partition
+#-----------------------------------------------------------------------------
+find_initrd_recovery_partition() {
+    EMMC_DEVICE="/dev/mmcblk0"
+    RET_PARTX=$("$PARTX" -s ${EMMC_DEVICE})
+    PART_INITRD=${EMMC_DEVICE}p$(IFS=; echo $RET_PARTX | "$AWK" 'tolower($6) == "ramdisk2" {print $1}')
+    if [ "z$PART_INITRD" == "z/dev/mmcblk0p" ]; then
+        PART_INITRD=${EMMC_DEVICE}p$(IFS=; echo $RET_PARTX | "$AWK" 'tolower($6) == "ramdisk" {print $1}')
+    fi
+}
+
+#-----------------------------------------------------------------------------
+#       Prepare parent directory
+#-----------------------------------------------------------------------------
+mkdir_p_parent() {
+    dst_dir=`"$DIRNAME" "$1"`
+    if [ ! -d "$dst_dir" -a ! -L "$dst_dir" ]; then
+        "$MKDIR" -p "$dst_dir"
+    fi
+}
+
+#-----------------------------------------------------------------------------
+#       Copy content to root of mounted image
+#-----------------------------------------------------------------------------
+do_copy() {
+    src=$1
+    dst="$INITRD_ROOT/$src"
+
+    if [ ! -e "$src" -o -e "$dst" ]; then
+        return
+    fi
+
+    mkdir_p_parent $dst
+
+    "$CP" -f "$src" "$dst"
+}
+
+#-----------------------------------------------------------------------------
+#       Get dependency libraries
+#-----------------------------------------------------------------------------
+get_dep_libs() {
+    "$LD_LINUX" --list $1 | "$SED" -r 's|^[^/]+([^ \(]+).*$|\1|'
+}
+
+#-----------------------------------------------------------------------------
+#       Gather initrd objects
+#-----------------------------------------------------------------------------
+get_initrd_objects() {
+    for f in $(ls ${OBJECTS_SPECIFY_DIR}); do
+        DIRECTORIES=
+        DIR_SYMLINKS=
+        VERBATIMS=
+        WITHLIBS=
+        LIBONLYS=
+        SYMLINKS=
+        source "${OBJECTS_SPECIFY_DIR}"/$f
+        OBJECTS_DIRECTORY="$OBJECTS_DIRECTORY $DIRECTORIES"
+        OBJECTS_DIR_SYMLINK="$OBJECTS_DIR_SYMLINK $DIR_SYMLINKS"
+        OBJECTS_VERBATIM="$OBJECTS_VERBATIM $VERBATIMS"
+        OBJECTS_WITHLIB="$OBJECTS_WITHLIB $WITHLIBS"
+        OBJECTS_LIBONLY="$OBJECTS_LIBONLY $LIBONLYS"
+        OBJECTS_SYMLINK="$OBJECTS_SYMLINK $SYMLINKS"
+    done
+
+    OBJECTS_DIRECTORY=$(echo "$OBJECTS_DIRECTORY" | sort | uniq)
+    OBJECTS_DIR_SYMLINK=$(echo "$OBJECTS_DIR_SYMLINK" | sort | uniq)
+    OBJECTS_VERBATIM=$(echo "$OBJECTS_VERBATIM" | sort | uniq)
+    OBJECTS_WITHLIB=$(echo "$OBJECTS_WITHLIB" | sort | uniq)
+    OBJECTS_LIBONLY=$(echo "$OBJECTS_LIBONLY" | sort | uniq)
+    OBJECTS_SYMLINK=$(echo "$OBJECTS_SYMLINK" | sort | uniq)
+}
+
+#-----------------------------------------------------------------------------
+#       Prepare directory objects
+#-----------------------------------------------------------------------------
+prepare_directory_objects() {
+    for dir in $@; do
+        "$MKDIR" -p "$INITRD_ROOT$dir"
+    done
+}
+
+#-----------------------------------------------------------------------------
+#       Copy verbatim objects
+#-----------------------------------------------------------------------------
+verbatim_objects() {
+    for obj in $@; do
+        do_copy $obj
+    done
+}
+
+#-----------------------------------------------------------------------------
+#       Copy withlib objects
+#-----------------------------------------------------------------------------
+withlib_objects() {
+    for content in $@; do
+        do_copy $content
+
+        DEP_LIBS=$(get_dep_libs $content)
+        for lib in $DEP_LIBS; do
+            do_copy $lib
+        done
+    done
+}
+
+#-----------------------------------------------------------------------------
+#       Copy libonly objects
+#-----------------------------------------------------------------------------
+libonly_objects() {
+    for content in $@; do
+        DEP_LIBS=$(get_dep_libs $content)
+        for lib in $DEP_LIBS; do
+            do_copy $lib
+        done
+    done
+}
+
+#-----------------------------------------------------------------------------
+#       Copy symlink objects
+#-----------------------------------------------------------------------------
+symlink_objects() {
+    for i in $@; do
+        if [ "z$i" == "z" ]; then
+            continue
+        fi
+
+        link=${i%:*}
+        target=${i#*:}
+        mkdir_p_parent "$INITRD_ROOT$link"
+        "$LN" -s "$target" "$INITRD_ROOT$link"
+    done
+}
+
+#-----------------------------------------------------------------------------
+#       Copy content
+#-----------------------------------------------------------------------------
+make_initrd_recovery() {
+    echo "copy initrd objects to $INITRD_ROOT"
+    get_initrd_objects
+
+    prepare_directory_objects $BASE_DIRECTORIES
+    symlink_objects $BASE_DIR_SYMLINKS
+    prepare_directory_objects $OBJECTS_DIRECTORY
+    symlink_objects $OBJECTS_DIR_SYMLINK
+    verbatim_objects $OBJECTS_VERBATIM
+    withlib_objects $OBJECTS_WITHLIB
+    libonly_objects $OBJECTS_LIBONLY
+    symlink_objects $OBJECTS_SYMLINK
+}
+
+#-----------------------------------------------------------------------------
+#       Check given parameter is mount point
+#-----------------------------------------------------------------------------
+check_mount_point() {
+    grep " $1 " /etc/mtab > /dev/null
+    if [ $? -ne 0 ]; then
+        echo "$1 is not mount point"
+        exit 0
+    fi
+}
+
+#-----------------------------------------------------------------------------
+#       Main
+#-----------------------------------------------------------------------------
+ARGS=$(getopt -o hp -l "help,post" -n "$0" -- "$@");
+
+eval set -- "$ARGS";
+
+while true; do
+    case "$1" in
+        -h|--help)
+            show_help >&2
+            exit 0
+            ;;
+        -p|--post)
+            OPT="post"
+            shift
+            ;;
+        --)
+            shift;
+            break;
+            ;;
+    esac
+done
+
+if [ $# -gt 1 ]; then
+    echo "Error: too many argument was given."
+    show_help >&2
+    exit 1
+fi
+
+case $OPT in
+    post)
+        find_initrd_recovery_partition
+        if [ "z$PART_INITRD" == "z/dev/mmcblk0p" ]; then
+            echo "Error: failed to find initrd partition"
+            exit 1
+        else
+            echo "Info: initrd partition: $PART_INITRD"
+        fi
+        mke2fs $PART_INITRD
+        e2fsck $PART_INITRD
+        mount $PART_INITRD $INITRD_ROOT
+        make_initrd_recovery
+        umount $INITRD_ROOT
+        ;;
+    *)
+        check_mount_point $INITRD_ROOT
+        make_initrd_recovery
+        ;;
+esac
diff --git a/src/librui/common.h b/src/librui/common.h
new file mode 100644 (file)
index 0000000..e874d83
--- /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..0b19be1
--- /dev/null
@@ -0,0 +1,45 @@
+/*-*- 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;
+} 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..e0255d2
--- /dev/null
@@ -0,0 +1,80 @@
+/*-*- 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 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..323a447
--- /dev/null
@@ -0,0 +1,143 @@
+/*-*- 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 my_backend = {
+        .init   = fbdev_init,
+        .flip   = fbdev_flip,
+        .exit   = fbdev_exit,
+        .data   = (void *)&fb_data
+};
+
+gr_backend *open_fbdev(void) {
+        return &my_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 ((signed int)fb->vi.yres_virtual <
+            fb->gr_framebuffer[0].height * 2)
+                fb->vi.yres_virtual = fb->gr_framebuffer[0].height * 2;
+
+        fb->vi.yoffset = n * fb->gr_framebuffer[0].height;
+        fb->vi.bits_per_pixel = fb->gr_framebuffer[0].pixel_bytes * 8;
+        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;
+        fbdev_common *fb = (fbdev_common *)backend->data;
+
+        if (!fbdev_init_common(backend))
+                return NULL;
+
+        bufsize = fb->vi.xres * fb->vi.yres * fb->vi.bits_per_pixel / 8;
+
+        /* Double buffer allocated as single piece of memory */
+        fb->gr_framebuffer[0].data = mmap(0, bufsize * 2,
+                                          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.c b/src/librui/graphics.c
new file mode 100644 (file)
index 0000000..207e28f
--- /dev/null
@@ -0,0 +1,469 @@
+/*-*- 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 <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"
+
+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 *px, *dst_p, *first_line;
+
+        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 = dst_p; i < width; i++) {
+                *px++ = gr_current_color.r;
+                *px++ = gr_current_color.g;
+                *px++ = gr_current_color.b;
+                px++; /* Alpha is not used on framebuffer */
+        }
+
+        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 *px, *dst_p, *first_line;
+
+        dst_p = gr->data;
+        for (i = 0, px = dst_p; i < gr->width; i++) {
+                *px++ = 0;
+                *px++ = 0;
+                *px++ = 0;
+                *px++ = 255;
+        }
+
+        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++) {
+                unsigned char *sx = src_p;
+                unsigned char *px = dst_p;
+
+                for (i = 0; i < w; i++) {
+                        unsigned char r = *sx++, g = *sx++, b = *sx++,
+                                a = *sx++;
+
+                        if (a == 255) {
+                                *px++ = r;
+                                *px++ = g;
+                                *px++ = b;
+                                px++; /* Alpha is not used on framebuffer */
+                        } else {
+                                *px = (*px * (255 - a) + r * a) / 255;
+                                ++px;
+                                *px = (*px * (255 - a) + g * a) / 255;
+                                ++px;
+                                *px = (*px * (255 - a) + b * a) / 255;
+                                px += 2;
+                        }
+                }
+
+                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++) {
+                unsigned char *sx = src_p;
+                unsigned char *px = dst_p;
+
+                for (i = 0; i < w; i++) {
+                        unsigned char r = *sx++, g = *sx++, b = *sx++;
+
+                        if (gr_current_color.a == 255) {
+                                *px++ = r;
+                                *px++ = g;
+                                *px++ = b;
+                                px++; /* Alpha is not used on framebuffer */
+                        } else {
+                                *px = (*px * (255 - gr_current_color.a) +
+                                       r * gr_current_color.a) / 255;
+                                ++px;
+                                *px = (*px * (255 - gr_current_color.a) +
+                                       g * gr_current_color.a) / 255;
+                                ++px;
+                                *px = (*px * (255 - gr_current_color.a) +
+                                       b * gr_current_color.a) / 255;
+                                px += 2;
+                        }
+                }
+
+                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;
+                unsigned char *px = dst_p;
+
+                for (i = 0; i < w; i++) {
+                        unsigned char gr = *sx++, a = *sx++;
+
+                        if (a == 255) {
+                                *px++ = gr;
+                                *px++ = gr;
+                                *px++ = gr;
+                                px++; /* Alpha is not used on framebuffer */
+                        } else {
+                                *px = (*px * (255 - a) + gr * a) / 255;
+                                ++px;
+                                *px = (*px * (255 - a) + gr * a) / 255;
+                                ++px;
+                                *px = (*px * (255 - a) + gr * a) / 255;
+                                px += 2;
+                        }
+                }
+
+                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;
+                unsigned char *px = 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.r;
+                                *px++ = gr_current_color.g;
+                                *px++ = gr_current_color.b;
+                                px++; /* Alpha is not used on framebuffer */
+                        } else {
+                                *px = (*px * (255 - a) +
+                                       gr_current_color.r * a) / 255;
+                                ++px;
+                                *px = (*px * (255 - a) +
+                                       gr_current_color.g * a) / 255;
+                                ++px;
+                                *px = (*px * (255 - a) +
+                                       gr_current_color.b * a) / 255;
+                                px += 2;
+                        }
+                }
+
+                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);
+        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));
+                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();
+
+        g_backend = open_fbdev();
+        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..ffaf146
--- /dev/null
@@ -0,0 +1,144 @@
+/*-*- 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>
+
+#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;
+
+typedef struct {
+        unsigned char r, g, b, a;
+} color;
+
+#define BLACK   (color) {   0,   0,   0, 255 }
+#define RED     (color) { 255,   0,   0, 255 }
+#define GREEN   (color) {   0, 255,   0, 255 }
+#define YELLOW  (color) { 255, 255,   0, 255 }
+#define BLUE    (color) {   0,   0, 255, 255 }
+#define MAGENTA (color) { 255,   0, 255, 255 }
+#define CYAN    (color) {   0, 255, 255, 255 }
+#define WHITE   (color) { 255, 255, 255, 255 }
+
+gr_backend *open_fbdev(void);
+
+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..fda1a8a
--- /dev/null
@@ -0,0 +1,217 @@
+/*-*- 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 <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#include <sys/poll.h>
+
+#include <linux/input.h>
+
+#include "input-events.h"
+
+#define MAX_DEVICES     16
+#define MAX_MISC_FDS    16
+
+#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_DEVICES + MAX_MISC_FDS];
+
+static unsigned ev_count = 0;
+static unsigned ev_misc_count = 0;
+
+bool ev_init(void) {
+        DIR *dir;
+        struct dirent *de;
+        int fd;
+
+        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_DEVICES)
+                        break;
+        }
+
+        closedir(dir);
+        if (ev_count == 0) {
+                printf("No input devices found.\n");
+                return false;
+        }
+
+        return true;
+}
+
+void ev_exit(void) {
+        while (ev_count > 0)
+                close(ev_fds[--ev_count].fd);
+
+        ev_misc_count = 0;
+}
+
+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;
+
+                        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..f84132c
--- /dev/null
@@ -0,0 +1,56 @@
+/*-*- 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 */
+
+typedef enum {
+        ACTION_NONE,
+        ACTION_DOWN,
+        ACTION_UP,
+        ACTION_CONFIRM,
+        ACTION_HOME,
+        ACTION_MENU,
+        ACTION_BACK
+} user_action;
+
+typedef enum {
+        ACTION_TYPE_IDLE,
+        ACTION_TYPE_BEGIN,
+        ACTION_TYPE_END,
+        ACTION_TYPE_LONGPRESS
+} 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..8d8a4bb
--- /dev/null
@@ -0,0 +1,520 @@
+/*-*- 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 (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..a78e617
--- /dev/null
@@ -0,0 +1,31 @@
+/*-*- 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..0554dcc
--- /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..2ac03b1
--- /dev/null
@@ -0,0 +1,70 @@
+/*-*- 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
+
+/* #define RUI_IMAGES_DIR  "/usr/share/librui/res/images" */
+#define RUI_IMAGES_DIR  "/usr/lib/system-recovery/res/images"
+
+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..3fc0e87
--- /dev/null
@@ -0,0 +1,149 @@
+/*-*- 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..1b6deb1
--- /dev/null
@@ -0,0 +1,93 @@
+/*-*- 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;
+
+        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)
+                menu->actions[item_selected].action_handler();
+
+        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..3cfe1e3
--- /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 void (*rui_menu_action_handler)(void);
+
+typedef struct {
+        int                     screen_switch_to;
+        rui_menu_action_handler action_handler;
+} 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..5d53d4e
--- /dev/null
@@ -0,0 +1,65 @@
+/*-*- 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..2243370
--- /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..4ca284a
--- /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..deff149
--- /dev/null
@@ -0,0 +1,35 @@
+/*-*- 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..685ff45
--- /dev/null
@@ -0,0 +1,113 @@
+/*-*- 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();
+        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..8f954c3
--- /dev/null
@@ -0,0 +1,71 @@
+/*-*- 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;
+} 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/minireboot/minireboot.c b/src/minireboot/minireboot.c
new file mode 100644 (file)
index 0000000..a0ce22a
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * 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 <stdio.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <linux/reboot.h>
+
+#include <sys/reboot.h>
+#include <sys/syscall.h>
+
+typedef enum {
+       ACTION_REBOOT,
+       ACTION_HALT,
+       ACTION_POWEROFF
+} action;
+
+enum {
+       OPT_HELP = 0x100,
+       OPT_HALT,
+       OPT_REBOOT,
+       OPT_NO_WALL
+};
+
+static struct option long_options[] = {
+       { "force",      no_argument,    NULL,   'f'         },
+       { "halt",       no_argument,    NULL,   OPT_HALT    },
+       { "help",       no_argument,    NULL,   OPT_HELP    },
+       { "no-sync",    no_argument,    NULL,   'n'         },
+       { "no-wall",    no_argument,    NULL,   OPT_NO_WALL },
+       { "no-wtmp",    no_argument,    NULL,   'd'         },
+       { "poweroff",   no_argument,    NULL,   'p'         },
+       { "reboot",     no_argument,    NULL,   OPT_REBOOT  },
+       { NULL,                   0,       0,    0          }
+};
+
+static const char *exe = NULL;
+
+/* ------------------------------------------------------------------------ */
+
+void
+usage(void)
+{
+       printf("Usage: %s [OPTION...] [ARG]\n"
+              "  -d --no-wtmp   Ignored in this version\n"
+              "  -f --force     Ignored in this version\n"
+              "  -n --no-sync   Ignored in this version\n"
+              "  -p --poweroff  Switch off the device\n"
+              "     --reboot    Reboot the device\n"
+              "     --halt      Halt the device\n"
+              "     --no-wall   Ignored in this version\n"
+              "     --help      Display this help and exit\n", exe);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int
+reboot_or_poweroff(action mode, const char *cmd)
+{
+       sync();
+       if (mode == ACTION_REBOOT) {
+               if (cmd) {
+                       printf("Rebooting with command \"%s\".", cmd);
+                       syscall(__NR_reboot, LINUX_REBOOT_MAGIC1,
+                               LINUX_REBOOT_MAGIC2,
+                               LINUX_REBOOT_CMD_RESTART2, cmd);
+                       perror("syscall(SYS_reboot)");
+               }
+
+               printf("Rebooting.\n");
+               reboot(RB_AUTOBOOT);
+       } else if (mode == ACTION_HALT) {
+               printf("Halting.\n");
+               reboot(RB_HALT_SYSTEM);
+       } else {
+               printf("Powering off.\n");
+               reboot(RB_POWER_OFF);
+       }
+
+       perror("reboot()");
+       return 1;
+}
+
+/* ------------------------------------------------------------------------ */
+
+int
+main(int argc, char *argv[])
+{
+       int c;
+       char *cmd = NULL;
+       action mode = ACTION_REBOOT;
+
+       exe = strrchr(argv[0], '/') ? strrchr(argv[0], '/') + 1 : argv[0];
+       opterr = 0;
+       while ((c = getopt_long(argc, argv, "dfnp", long_options,
+                               NULL)) >= 0) {
+               switch (c) {
+                       case OPT_HALT:
+                               mode = ACTION_HALT;
+                               break;
+                       case OPT_REBOOT:
+                               mode = ACTION_REBOOT;
+                               break;
+                       case 'p':
+                               mode = ACTION_POWEROFF;
+                               break;
+                       case 'd':
+                       case 'f':
+                       case 'n':
+                       case OPT_NO_WALL:
+                               break; /* Ignore option */
+                       case OPT_HELP:
+                               usage();
+                               exit(0);
+                       default:
+                               usage();
+                               exit(1);
+               }
+       }
+
+       if (mode == ACTION_REBOOT && argc == optind + 1)
+               cmd = argv[optind];
+        else if (optind < argc) {
+                printf("Too many arguments.\n");
+               usage();
+                exit(1);
+       }
+
+       return reboot_or_poweroff(mode, cmd);
+}
diff --git a/src/shared/log.c b/src/shared/log.c
new file mode 100644 (file)
index 0000000..554f720
--- /dev/null
@@ -0,0 +1,309 @@
+/*-*- 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 <libsystem/libsystem.h>
+
+#include "log.h"
+
+#define FILEBUF 1024
+
+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 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: %s\n", strerror(-r));
+
+        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..f37f328
--- /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.list.m4 b/src/system-recovery/50-system-recovery.list.m4
new file mode 100644 (file)
index 0000000..99ab2aa
--- /dev/null
@@ -0,0 +1,48 @@
+# ---- Target contents ----------------------------------------------------- #
+DIRECTORIES="
+/dev
+/etc
+/proc
+/smack
+/sys
+/system
+/tmp
+/usr/bin
+/usr/lib
+/usr/sbin
+"
+
+DIR_SYMLINKS="
+/bin:usr/bin
+/lib:usr/lib
+/sbin:usr/sbin
+"
+
+VERBATIMS="
+/usr/lib/system-recovery/recovery-init
+m4_ifdef(`RECOVERY_GUI',
+`/usr/lib/system-recovery/res/images/font.png
+/usr/lib/system-recovery/res/images/menu-title.png
+/usr/lib/system-recovery/res/images/tizen-anim.png
+/usr/lib/system-recovery/res/images/warning.png')
+"
+
+WITHLIBS="
+/usr/bin/awk
+/usr/bin/bash
+/usr/bin/grep
+/usr/bin/mount
+/usr/bin/sync
+/usr/bin/touch
+/usr/bin/umount
+/usr/lib/initrd-recovery/minireboot
+/usr/sbin/partx
+m4_ifdef(`RECOVERY_GUI', `/usr/lib/system-recovery/system-recovery')
+m4_ifdef(`WITH_DM_VERITY', `/usr/bin/verityctl')
+"
+
+# LinkFileName:Target
+SYMLINKS="
+/usr/bin/system-recovery:/usr/lib/system-recovery/system-recovery
+/sbin/recovery-init:/usr/lib/system-recovery/recovery-init
+"
diff --git a/src/system-recovery/minvconf.c b/src/system-recovery/minvconf.c
new file mode 100644 (file)
index 0000000..8c6e514
--- /dev/null
@@ -0,0 +1,159 @@
+/*-*- 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 <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#include <linux/limits.h>
+
+#include <vconf/vconf.h>
+
+#include "minvconf.h"
+#include "system-recovery.h"
+
+#define COMBINE_FOLDER
+
+#ifdef COMBINE_FOLDER
+
+static bool convert_key_name(char *path) {
+        if (!(path = strchr(path, '/'))) {
+                printf("Wrong key path: \"%s\"!", path);
+                return false;
+        }
+
+        while ((path = strchr(path + 1, '/')))
+                *path = '+';
+
+        return true;
+}
+
+#endif /* COMBINE_FOLDER */
+
+/* The path of the key file is returned with ROOT_MOUNT_DIR prefix. */
+static bool get_key_path(const char *keyname, char *path, size_t bufsize) {
+        const char *key = keyname;
+        int key_offset;
+
+        if (!keyname || !path)
+                return false;
+
+        /* Not supported "memory/..." keys because they are not stored
+         * on the disk and can't be accessed in recovery mode. */
+        if (strstr(key, VCONF_BACKEND_DB_PREFIX) == key ||
+            strstr(key, VCONF_BACKEND_FILE_PREFIX) == key)
+                snprintf(path, bufsize, ROOT_MOUNT_DIR "%s%n%s",
+                         VCONF_BACKEND_SYSTEM_DIR, &key_offset, key);
+        else {
+                printf("Wrong prefix of vconf key \"%s\"", key);
+                return false;
+        }
+
+#ifdef COMBINE_FOLDER
+        if (!convert_key_name(path + key_offset))
+                return false;
+#endif /* COMBINE_FOLDER */
+
+        return true;
+}
+
+/* Acquire shared (read) lock for entire file. */
+static bool file_lock_read(FILE *f) {
+        struct flock lock = {
+                .l_type         = F_RDLCK,
+                .l_start        = 0,
+                .l_whence       = SEEK_SET,
+                .l_len          = 0 /* Whole file */
+        };
+
+        if (fcntl(fileno(f), F_SETLK, &lock) < 0) {
+                perror("Can't acquire read-lock for a file");
+                return false;
+        }
+
+        return true;
+}
+
+static bool file_unlock(FILE *f) {
+        struct flock lock = {
+                .l_type         = F_UNLCK,
+                .l_start        = 0,
+                .l_whence       = SEEK_SET,
+                .l_len          = 0 /* Whole file */
+        };
+
+        if (fcntl(fileno(f), F_SETLK, &lock) < 0) {
+                perror("Can't unlock file");
+                return false;
+        }
+
+        return true;
+}
+
+bool mvconf_get_int(const char *key, int *val) {
+        int type;
+        char fname[PATH_MAX];
+        bool ret = false;
+        FILE *f;
+
+        if (!key || !val)
+                return false;
+
+        if (!get_key_path(key, fname, sizeof(fname))) {
+                printf("Can't get file path for vconf key \"%s\".\n", key);
+                return false;
+        }
+
+        if (!(f = fopen(fname, "r"))) {
+                printf("Can't open vconf key file \"%s\": %m.\n", fname);
+                return false;
+        }
+
+        if (!file_lock_read(f))
+                goto exit_close;
+
+        if (fread(&type, sizeof(int), 1, f) != 1) {
+                printf("Can't read type of vconf key from the file \"%s\".\n",
+                       fname);
+                goto exit_unlock;
+        }
+
+        if (type != VCONF_TYPE_INT) {
+                printf("Wrong type %d of vconf key \"%s\".\n", type, key);
+                goto exit_unlock;
+        }
+
+        if (fread(val, sizeof(int), 1, f) != 1) {
+                printf("Can't read value of vconf key from the file "
+                       "\"%s\".\n", fname);
+                goto exit_unlock;
+        }
+
+        ret = true;
+
+exit_unlock:
+        file_unlock(f);
+exit_close:
+        fclose(f);
+        return ret;
+}
diff --git a/src/system-recovery/minvconf.h b/src/system-recovery/minvconf.h
new file mode 100644 (file)
index 0000000..4a5a44a
--- /dev/null
@@ -0,0 +1,30 @@
+/*-*- 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>
+
+/* These prefixes are defined in vconf-internals.h which is not installed,
+ * so redefining it here with VCONF_ prefix. */
+#define VCONF_BACKEND_DB_PREFIX         "db/"
+#define VCONF_BACKEND_FILE_PREFIX       "file/"
+
+#define VCONF_BACKEND_SYSTEM_DIR        "/opt/var/kdb/"
+
+bool mvconf_get_int(const char *key, int *val);
diff --git a/src/system-recovery/process-util.c b/src/system-recovery/process-util.c
new file mode 100644 (file)
index 0000000..3156a59
--- /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 : %s\n", pid,
+                             strerror(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..04e601f
--- /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-init.in b/src/system-recovery/recovery-init.in
new file mode 100644 (file)
index 0000000..6197e86
--- /dev/null
@@ -0,0 +1,102 @@
+#!/bin/bash
+
+SYSTEM_RECOVERY="/usr/bin/system-recovery"
+FAKE_ROOT=/system
+
+AWK="/usr/bin/awk"
+GREP="/usr/bin/grep"
+MOUNT="/usr/bin/mount"
+PARTX="/usr/sbin/partx"
+REBOOT="/usr/lib/initrd-recovery/minireboot"
+SYNC="/usr/bin/sync"
+TOUCH="/usr/bin/touch"
+UMOUNT="/usr/bin/umount"
+VERITYCTL="/usr/bin/verityctl"
+
+#------------------------------------------------
+#       get partition id
+#------------------------------------------------
+get_partition_id() {
+    EMMC_DEVICE="/dev/mmcblk0"
+    RET_PARTX=$("$PARTX" -s ${EMMC_DEVICE})
+    PART_ROOTFS=${EMMC_DEVICE}p$(IFS=; echo $RET_PARTX | "$AWK" 'tolower($6) == "rootfs" {print $1}')
+    PART_SYSTEM_DATA=${EMMC_DEVICE}p$(IFS=; echo $RET_PARTX | "$AWK" 'tolower($6) == "system-data" {print $1}')
+    PART_USER=${EMMC_DEVICE}p$(IFS=; echo $RET_PARTX | "$AWK" 'tolower($6) == "user" {print $1}')
+    PART_CSC=${EMMC_DEVICE}p$(IFS=; echo $RET_PARTX | "$AWK" 'tolower($6) == "csc" {print $1}')
+    PART_MODULES=${EMMC_DEVICE}p$(IFS=; echo $RET_PARTX | "$AWK" 'tolower($6) == "module" {print $1}')
+}
+
+#------------------------------------------------
+#       mount_partitions
+#------------------------------------------------
+mount_partitions() {
+    echo "mount partitions"
+    get_partition_id
+
+    if [ -e "$VERITYCTL" ]; then
+       "$VERITYCTL" dump ${PART_ROOTFS} | "$GREP" "HASH mode" | "$GREP" "on" > /dev/null
+       if [ $? -eq 0 ]; then
+            "$VERITYCTL" create rootfs ${PART_ROOTFS}
+            "$MOUNT" -t ext4 /dev/mapper/rootfs ${FAKE_ROOT} -o ro
+       else
+            "$MOUNT" -t ext4 ${PART_ROOTFS} ${FAKE_ROOT} -o ro
+       fi
+    else
+       "$MOUNT" -t ext4 ${PART_ROOTFS} ${FAKE_ROOT} -o ro
+    fi
+
+    "$MOUNT" -t ext4 ${PART_SYSTEM_DATA} ${FAKE_ROOT}/opt
+    "$MOUNT" -t ext4 ${PART_USER} ${FAKE_ROOT}/opt/usr
+    "$MOUNT" -t ext4 ${PART_CSC} ${FAKE_ROOT}/opt/system/csc
+
+    "$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"
+    get_partition_id
+
+    "$UMOUNT" ${FAKE_ROOT}/opt/system/csc
+    "$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
+if [ "z@RECOVERY_GUI@" == "zGUI" ]; then
+    "$SYSTEM_RECOVERY"
+else
+    $TOUCH ${FAKE_ROOT}/opt/.factoryreset
+    if [ $? -ne 0 ]; then
+        echo "Error: failed to put factory reset file flag."
+    fi
+fi
+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..60346a6
--- /dev/null
@@ -0,0 +1,108 @@
+/*-*- 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 <fcntl.h>
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/reboot.h>
+
+#include <vconf/vconf-keys.h>
+
+#include "rui.h"
+#include "common.h"
+#include "graphics.h"
+#include "minvconf.h"
+#include "input-events.h"
+#include "process-util.h"
+#include "system-recovery.h"
+#include "rui-progress-bar.h"
+
+bool volatile running = true;
+
+void sys_power_reboot(void) {
+        reboot(RB_AUTOBOOT);
+}
+
+void boot_safe_mode(void) {
+        int fd;
+
+        if ((fd = creat(SAFE_MODE_FILE, 0664)) < 0) {
+                LOGD("Can't enable safe mode.\n");
+                return; /* TODO: Display error message! */
+        }
+
+        LOGD("Safe-mode enabled.\n");
+        close(fd);
+        running = false;
+}
+
+void run_factory_reset(void) {
+        /* int r UNUSED; */
+        /* char *argv[2] = { FACTORY_RESET, NULL }; */
+
+        /* if (pivot_root(ROOT_MOUNT_DIR, INITRD_MOUNT_DIR)) { */
+        /*         perror("pivot_root() failed"); */
+        /*         return; /\* TODO: Display error message! *\/ */
+        /* } */
+
+        /* r = chdir("/"); */
+        /* process_exec(PROCESS_NON_WAIT, argv); */
+
+       /* creat(INITRD_MOUNT_DIR "/opt/.factoryreset-test", 0644); */
+       int fd;
+
+       if ((fd = creat("/opt/.factoryreset", 0644)) < 0) {
+               LOGD("Can't factory reset.\n");
+               return;
+       }
+       sync();
+       close(fd);
+       reboot(RB_AUTOBOOT);
+}
+
+int main(void) {
+        LOGD("[main] recovery started.\n");
+        if (!recovery_rui_init()) {
+                LOGD("Can't initialize GUI.\n");
+                return 1;
+        }
+
+        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();
+        LOGD("[main] recovery finished.\n");
+        return 0;
+}
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..cb927c1
--- /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) {  27, 199, 204, 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..97c7e0f
--- /dev/null
@@ -0,0 +1,402 @@
+/*-*- 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"
+#include "system-recovery.h"
+#include "rui-progress-bar.h"
+#include "recovery-rui-skin.h"
+
+static rui_image rui_images[] = {
+        [RECOVERY_RUI_IMAGE_BACKGROUND_DEFAULT] = {
+                .fname          = RUI_RECOVERY_IMAGES_DIR "/warning.png",
+                .c_bg           = RUI_COLOR_BACKGROUND,
+                .align_hor      = GR_ALIGN_CENTER,
+                .align_ver      = GR_ALIGN_BOTTOM,
+                .offset_x       = 0,
+                .offset_y       = 0,
+                .img_type       = GR_WITH_ALPHA,
+                .surface        = NULL
+        }, [RECOVERY_RUI_IMAGE_MENU_TITLE] = {
+                .fname          = RUI_RECOVERY_IMAGES_DIR "/menu-title.png",
+                .c_bg           = RUI_COLOR_TITLE,
+                .align_hor      = GR_ALIGN_CENTER,
+                .align_ver      = GR_ALIGN_TOP,
+                .offset_x       = 0,
+                .offset_y       = 20,
+                .img_type       = GR_WITH_ALPHA,
+                .surface        = NULL
+        }
+};
+
+static rui_animation rui_animations[] = {
+        [RECOVERY_RUI_ANIMATION_WORKING] = {
+                .fname          = RUI_RECOVERY_IMAGES_DIR "/tizen-anim.png",
+                .c_bg           = RUI_COLOR_BACKGROUND,
+                .align_hor      = GR_ALIGN_CENTER,
+                .align_ver      = GR_ALIGN_MIDDLE,
+                .offset_x       = 0,
+                .offset_y       = 0,
+                .frames_num     = 0,
+                .current_frame  = 0,
+                .img_type       = GR_WITH_ALPHA,
+                .surfaces       = NULL
+        }
+};
+
+static rui_menu_style rui_menu_common_style = {
+        .item_height            = RUI_MENU_ITEM_HEIGHT,
+        .item_spacing           = RUI_MENU_ITEM_SPACING,
+        .text_pos_x             = RUI_MENU_TEXT_POS_X,
+        .c_bg_selected          = RUI_COLOR_MENU_BG_SELECTED,
+        .c_bg_unselected        = RUI_COLOR_MENU_BG_UNSELECTED,
+        .c_text_selected        = RUI_COLOR_MENU_TEXT_SELECTED,
+        .c_text_unselected      = RUI_COLOR_MENU_TEXT_UNSELECTED
+};
+
+static const char *rui_main_menu_items[] = {
+        "Reboot system now",
+        "Safe mode",
+        "Phone reinitialization",
+};
+
+static const char *rui_confirm_menu_items[] = {
+        "Yes",
+        "No"
+};
+
+static rui_menu_action rui_main_menu_actions[] = {
+        {
+                .screen_switch_to       = RECOVERY_RUI_SCREEN_REBOOT,
+                .action_handler         = NULL
+        }, {
+                .screen_switch_to       = RECOVERY_RUI_SCREEN_SAFE,
+                .action_handler         = NULL
+        }, {
+                .screen_switch_to       = RECOVERY_RUI_SCREEN_FACTORY,
+                .action_handler         = NULL
+        }
+};
+
+ASSERT_ARRAYS_EQUAL_LENGTH(rui_main_menu_actions, rui_main_menu_items);
+
+static rui_menu rui_main_menu = {
+        .pos_x          = RUI_MAIN_MENU_POS_X,
+        .pos_y          = RUI_MAIN_MENU_POS_Y,
+        .style          = &rui_menu_common_style,
+        .items          = rui_main_menu_items,
+        .items_num      = ARRAY_SIZE(rui_main_menu_items),
+        .item_selected  = 0,
+        .item_default   = RUI_MENU_ITEM_DO_NOT_CHANGE,
+        .actions        = rui_main_menu_actions
+};
+
+static rui_menu_action rui_reboot_menu_actions[] = {
+        {
+                .screen_switch_to       = RUI_SCREEN_CURRENT,
+                .action_handler         = sys_power_reboot
+        }, {
+                .screen_switch_to       = RUI_SCREEN_BACK,
+                .action_handler         = NULL
+        }
+};
+
+ASSERT_ARRAYS_EQUAL_LENGTH(rui_reboot_menu_actions, rui_confirm_menu_items);
+
+static rui_menu rui_reboot_menu = {
+        .pos_x          = RUI_REBOOT_MENU_POS_X,
+        .pos_y          = RUI_REBOOT_MENU_POS_Y,
+        .style          = &rui_menu_common_style,
+        .items          = rui_confirm_menu_items,
+        .items_num      = ARRAY_SIZE(rui_confirm_menu_items),
+        .item_selected  = 1,
+        .item_default   = 1,
+        .actions        = rui_reboot_menu_actions
+};
+
+static rui_menu_action rui_safe_menu_actions[] = {
+        {
+                .screen_switch_to       = RUI_SCREEN_CURRENT,
+                .action_handler         = boot_safe_mode
+        }, {
+                .screen_switch_to       = RUI_SCREEN_BACK,
+                .action_handler         = NULL
+        }
+};
+
+ASSERT_ARRAYS_EQUAL_LENGTH(rui_safe_menu_actions, rui_confirm_menu_items);
+
+static rui_menu rui_safe_menu = {
+        .pos_x          = RUI_SAFE_MENU_POS_X,
+        .pos_y          = RUI_SAFE_MENU_POS_Y,
+        .style          = &rui_menu_common_style,
+        .items          = rui_confirm_menu_items,
+        .items_num      = ARRAY_SIZE(rui_confirm_menu_items),
+        .item_selected  = 1,
+        .item_default   = 1,
+        .actions        = rui_safe_menu_actions
+};
+
+static rui_menu_action rui_factory_menu_actions[] = {
+        {
+                .screen_switch_to       = RECOVERY_RUI_SCREEN_FACTORY_RUN,
+                .action_handler         = run_factory_reset
+        }, {
+                .screen_switch_to       = RUI_SCREEN_BACK,
+                .action_handler         = NULL
+        }
+};
+
+ASSERT_ARRAYS_EQUAL_LENGTH(rui_factory_menu_actions, rui_confirm_menu_items);
+
+static rui_menu rui_factory_menu = {
+        .pos_x          = RUI_FACTORY_MENU_POS_X,
+        .pos_y          = RUI_FACTORY_MENU_POS_Y,
+        .style          = &rui_menu_common_style,
+        .items          = rui_confirm_menu_items,
+        .items_num      = ARRAY_SIZE(rui_confirm_menu_items),
+        .item_selected  = 1,
+        .item_default   = 1,
+        .actions        = rui_factory_menu_actions
+};
+
+static rui_description_style rui_description_common_style = {
+        .c_title        = RUI_COLOR_DESCRIPTION_TITLE,
+        .c_text         = RUI_COLOR_DESCRIPTION_TEXT
+};
+
+static rui_description rui_main_screen_description = {
+        .pos_x          = RUI_MAIN_SCREEN_DESCRIPTION_POS_X,
+        .pos_y          = RUI_MAIN_SCREEN_DESCRIPTION_POS_Y,
+        .style          = &rui_description_common_style,
+        .title          = "Controls:",
+        .text           = "Volume Up/Down to move menu cursor\n"
+        "Power button to select"
+};
+
+static rui_description rui_reboot_screen_description = {
+        .pos_x          = RUI_REBOOT_SCREEN_DESCRIPTION_POS_X,
+        .pos_y          = RUI_REBOOT_SCREEN_DESCRIPTION_POS_Y,
+        .style          = &rui_description_common_style,
+        .title          = "The phone will be restarted.",
+        .text           = "Continue?"
+};
+
+static rui_description rui_safe_screen_description = {
+        .pos_x          = RUI_SAFE_SCREEN_DESCRIPTION_POS_X,
+        .pos_y          = RUI_SAFE_SCREEN_DESCRIPTION_POS_Y,
+        .style          = &rui_description_common_style,
+        .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?"
+};
+
+static rui_description rui_factory_screen_description = {
+        .pos_x          = RUI_FACTORY_SCREEN_DESCRIPTION_POS_X,
+        .pos_y          = RUI_FACTORY_SCREEN_DESCRIPTION_POS_Y,
+        .style          = &rui_description_common_style,
+        .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?"
+};
+
+static rui_description rui_factory_run_screen_description = {
+        .pos_x          = RUI_FACTORY_RUN_SCREEN_DESCRIPTION_POS_X,
+        .pos_y          = RUI_FACTORY_RUN_SCREEN_DESCRIPTION_POS_Y,
+        .style          = &rui_description_common_style,
+        .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.)"
+};
+
+static rui_ruler_style rui_ruler_common_style = {
+        .c_ruler        = RUI_COLOR_RULER
+};
+
+static rui_ruler rui_main_screen_rulers[] = {
+        {       /* After menu title */
+                .pos_x  = RUI_RULER_TOP_POS_X,
+                .pos_y  = RUI_RULER_TOP_POS_Y,
+                .height = RUI_RULER_HEIGHT,
+                .style  = &rui_ruler_common_style
+        }, {    /* After main menu */
+                .pos_x  = RUI_RULER_TOP_POS_X,
+                .pos_y  = RUI_MAIN_SCREEN_RULER_POS_Y,
+                .height = RUI_RULER_HEIGHT,
+                .style  = &rui_ruler_common_style
+        }, {    /* End marker */
+                .pos_x  = 0,
+                .pos_y  = 0,
+                .height = 0,
+                .style  = NULL
+        }
+};
+
+/* Both for reboot and safe mode screens */
+static rui_ruler rui_confirm_screens_rulers[] = {
+        {       /* After menu title */
+                .pos_x  = RUI_RULER_TOP_POS_X,
+                .pos_y  = RUI_RULER_TOP_POS_Y,
+                .height = RUI_RULER_HEIGHT,
+                .style  = &rui_ruler_common_style
+        }, {    /* End marker */
+                .pos_x  = 0,
+                .pos_y  = 0,
+                .height = 0,
+                .style  = NULL
+        }
+};
+
+static rui_screen_style rui_screen_common_style = {
+        .c_background   = RUI_COLOR_BACKGROUND
+};
+
+static int rui_common_screen_images[] = {
+        RECOVERY_RUI_IMAGE_BACKGROUND_DEFAULT,
+        RECOVERY_RUI_IMAGE_MENU_TITLE,
+        RUI_IMAGE_NONE /* Stop element */
+};
+
+static int rui_common_run_screen_images[] = {
+        RECOVERY_RUI_IMAGE_MENU_TITLE,
+        RUI_IMAGE_NONE /* Stop element */
+};
+
+static int rui_factory_run_screen_animations[] = {
+        RECOVERY_RUI_ANIMATION_WORKING,
+        RUI_ANIMATION_NONE /* Stop element */
+};
+
+static rui_screen rui_screens[] = {
+        [RECOVERY_RUI_SCREEN_MAIN] = {
+                .style                  = &rui_screen_common_style,
+                .menu                   = &rui_main_menu,
+                .description            = &rui_main_screen_description,
+                .rulers                 = rui_main_screen_rulers,
+                .progress_bar           = NULL,
+                .images                 = rui_common_screen_images,
+                .animations             = NULL,
+                .on_enter               = NULL,
+                .draw                   = NULL,
+                .screen_back            = RUI_SCREEN_CURRENT
+        }, [RECOVERY_RUI_SCREEN_REBOOT] = {
+                .style                  = &rui_screen_common_style,
+                .menu                   = &rui_reboot_menu,
+                .description            = &rui_reboot_screen_description,
+                .rulers                 = rui_confirm_screens_rulers,
+                .progress_bar           = NULL,
+                .images                 = rui_common_screen_images,
+                .animations             = NULL,
+                .on_enter               = NULL,
+                .draw                   = NULL,
+                .screen_back            = RECOVERY_RUI_SCREEN_MAIN
+        }, [RECOVERY_RUI_SCREEN_SAFE] = {
+                .style                  = &rui_screen_common_style,
+                .menu                   = &rui_safe_menu,
+                .description            = &rui_safe_screen_description,
+                .rulers                 = rui_confirm_screens_rulers,
+                .progress_bar           = NULL,
+                .images                 = rui_common_screen_images,
+                .animations             = NULL,
+                .on_enter               = NULL,
+                .draw                   = NULL,
+                .screen_back            = RECOVERY_RUI_SCREEN_MAIN
+        }, [RECOVERY_RUI_SCREEN_FACTORY] = {
+                .style                  = &rui_screen_common_style,
+                .menu                   = &rui_factory_menu,
+                .description            = &rui_factory_screen_description,
+                .rulers                 = rui_confirm_screens_rulers,
+                .progress_bar           = NULL,
+                .images                 = rui_common_screen_images,
+                .animations             = NULL,
+                .on_enter               = NULL,
+                .draw                   = NULL,
+                .screen_back            = RECOVERY_RUI_SCREEN_MAIN
+        }, [RECOVERY_RUI_SCREEN_FACTORY_RUN] = {
+                .style                  = &rui_screen_common_style,
+                .menu                   = NULL,
+                .description            = &rui_factory_run_screen_description,
+                .rulers                 = rui_confirm_screens_rulers,
+                .progress_bar           = NULL,
+                .images                 = rui_common_run_screen_images,
+                .animations             = rui_factory_run_screen_animations,
+                .on_enter               = NULL,
+                .draw                   = NULL,
+                .screen_back            = RUI_SCREEN_CURRENT
+        }
+};
+
+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)
+                return;
+
+        cs = get_current_screen();
+        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 (get_current_screen_id() == RECOVERY_RUI_SCREEN_FACTORY_RUN &&
+                 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_NONE || action_type != ACTION_TYPE_IDLE ||
+                 !cs->animations)
+                need_repaint = 0;
+
+        if (need_repaint)
+                rui_draw();
+}
+
+bool recovery_rui_init(void) {
+        return rui_init(rui_screens, ARRAY_SIZE(rui_screens),
+                        RECOVERY_RUI_SCREEN_MAIN,
+                        rui_images, ARRAY_SIZE(rui_images),
+                        rui_animations, ARRAY_SIZE(rui_animations));
+}
+
+void recovery_rui_exit(void) {
+        rui_exit();
+}
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..348016d
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+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..b6f8e0d
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+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.h b/src/system-recovery/system-recovery.h
new file mode 100644 (file)
index 0000000..614c40c
--- /dev/null
@@ -0,0 +1,73 @@
+/*-*- 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>
+#include <stdbool.h>
+
+#include "input-events.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LOGD                    printf
+#define FILE_IO_BUF_SIZE        128
+
+#define SAFE_MODE_FILE          "/opt/etc/.safeboot"
+#define ROOT_MOUNT_DIR          "/system"
+#define INITRD_MOUNT_DIR        "/system/mnt/initrd-recovery"
+#define FACTORY_RESET           "/usr/bin/factory-reset"
+
+#define RUI_RECOVERY_IMAGES_DIR "/usr/lib/system-recovery/res/images"
+
+typedef enum {
+        RECOVERY_RUI_SCREEN_MAIN,
+        RECOVERY_RUI_SCREEN_REBOOT,
+        RECOVERY_RUI_SCREEN_SAFE,
+        RECOVERY_RUI_SCREEN_FACTORY,
+        RECOVERY_RUI_SCREEN_FACTORY_RUN,
+        RECOVERY_RUI_SCREEN_SD_RESTORE,
+        RECOVERY_RUI_SCREEN_SD_RESTORE_RUN
+} recovery_rui_screen_id;
+
+typedef enum {
+        RECOVERY_RUI_IMAGE_BACKGROUND_DEFAULT,
+        RECOVERY_RUI_IMAGE_MENU_TITLE
+} recovery_rui_image_id;
+
+typedef enum {
+        RECOVERY_RUI_ANIMATION_WORKING
+} recovery_rui_animation_id;
+
+int pivot_root(const char *new_root, const char *put_old);
+
+void sys_power_reboot(void);
+void boot_safe_mode(void);
+void run_factory_reset(void);
+void sd_restore(void);
+
+bool recovery_rui_init(void);
+void recovery_rui_exit(void);
+void recovery_rui_input_callback(user_action action,
+                                 user_action_type action_type);
+
+#ifdef __cplusplus
+}
+#endif