[prev in list] [next in list] [prev in thread] [next in thread]
List: busybox
Subject: [patch] - bbsplash
From: Michele Sanges <michele.sanges () otomelara ! it>
Date: 2008-02-28 13:42:16
Message-ID: 1204206136.30494.4.camel () pigreco
[Download RAW message or body]
Please, consider the new version of the patch.
Many thanks
Michele Sanges
["bbsplash_28_02_2008.diff" (bbsplash_28_02_2008.diff)]
diff -urP busybox-1.9.1/include/applets.h busybox-1.9.1_bbsplash/include/applets.h
--- busybox-1.9.1/include/applets.h 2008-02-12 17:03:10.000000000 +0100
+++ busybox-1.9.1_bbsplash/include/applets.h 2008-02-28 14:13:24.000000000 +0100
@@ -86,6 +86,7 @@
USE_BASENAME(APPLET_NOFORK(basename, basename, _BB_DIR_USR_BIN, _BB_SUID_NEVER, \
basename)) USE_BBCONFIG(APPLET(bbconfig, _BB_DIR_BIN, _BB_SUID_NEVER))
//USE_BBSH(APPLET(bbsh, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_BBSPLASH(APPLET(bbsplash, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_BUNZIP2(APPLET(bunzip2, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_BUNZIP2(APPLET_ODDNAME(bzcat, bunzip2, _BB_DIR_USR_BIN, _BB_SUID_NEVER, bzcat))
USE_BZIP2(APPLET(bzip2, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
diff -urP busybox-1.9.1/include/usage.h busybox-1.9.1_bbsplash/include/usage.h
--- busybox-1.9.1/include/usage.h 2008-02-12 17:03:10.000000000 +0100
+++ busybox-1.9.1_bbsplash/include/usage.h 2008-02-28 14:13:24.000000000 +0100
@@ -119,6 +119,17 @@
"$ basename /foo/bar.txt .txt\n" \
"bar"
+#define bbsplash_trivial_usage \
+ "-[cd] /dev/fbx"
+#define bbsplash_full_usage \
+ "Options:\n" \
+ " -c to hide the cursor\n" \
+ " -d /dev/fbn to select another framebuffer device that /dev/fb0\n"
+#define bbsplash_example_usage \
+ "$ setsid bbsplash [-cd] /dev/fbx (start the daemon)" \
+ "$ echo val > /dev/bbsplash_fifo (where val=0..100 - show a progress bar of \
value val)\n" \ + "$ echo exit > /dev/bbsplash_fifo (kill the daemon)\n"
+
#define bunzip2_trivial_usage \
"[OPTION]... [FILE]"
#define bunzip2_full_usage \
diff -urP busybox-1.9.1/miscutils/bbsplash.c \
busybox-1.9.1_bbsplash/miscutils/bbsplash.c
--- busybox-1.9.1/miscutils/bbsplash.c 1970-01-01 01:00:00.000000000 +0100
+++ busybox-1.9.1_bbsplash/miscutils/bbsplash.c 2008-02-28 14:21:24.000000000 +0100
@@ -0,0 +1,412 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * boot splash implementation for busybox
+ *
+ * Copyright (C) 2008 Michele Sanges <michele.sanges@otomelara.it> \
<pigrecoq@libero.it> + *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * If you want logging messages on /dev/bbsplash_log, change the DEBUG define to 1 \
in the source. + *
+ * Usage:
+ * - pass to the kernel the options 'vga=xxx' to enable the framebuffer with the \
correct resolution + * - make the directory '/etc/bbsplash' and put in it the files \
'bbsplash.ini' and the splash image in .ppm format. + * - configure the applet by \
editing the .ini file. + * - start the applet: $ setsid bbsplash <params>
+ * where <params> can be:
+ * -c: to hide the cursor; -d /dev/fbn: to select another framebuffer device that \
/dev/fb0 + * - if you want run the applet only in presence of a kernel parameter (for \
example bbsplash=on), type: + * $ grep -q "bbsplash=on" < /proc/cmdline && setsid \
bbsplash <params> + * - send to the /dev/bbsplash_fifo the following messages:
+ * (1) the percentage of the boot process.
+ * (2) 'exit' in order to kill the applet.
+ *
+ * TODO:- other image formats management
+ * - text management to display short sentences
+ */
+
+/**
+ * boot splash implementation for busybox
+ * \file: bbsplash.c
+ * \author Michele Sanges <michele.sanges@otomelara.it> <pigrecoq@gmail.com>
+ * \version 1.0.0
+ * \date 28/02/2008
+ */
+
+#include "libbb.h"
+#include <linux/fb.h>
+
+#define DEBUG 0
+
+struct globals {
+#if DEBUG
+ bool bdebug_messages; ///< flag for enable/disable writing messages in logfile
+ FILE *logfile_fd; ///< log file
+#endif
+ int fbfd; ///< descriptor of framebuffer device
+ FILE *theme_file; ///< splash file
+ unsigned char *addr; ///< pointer to framebuffer memory
+ unsigned nbar_width; ///< progress bar width
+ unsigned nbar_height; ///< progress bar height
+ unsigned nbar_posx; ///< progress bar orizzontal position
+ unsigned nbar_posy; ///< progress bar vertical position
+ unsigned char nbar_colr; ///< progress bar colour red component
+ unsigned char nbar_colg; ///< progress bar colour green component
+ unsigned char nbar_colb; ///< progress bar colour blue component
+ char strsplash_theme[40];///< name of the splash theme
+ struct fb_var_screeninfo screen_infovar;
+ struct fb_fix_screeninfo screen_infofix;
+};
+
+#define G (*ptr_to_globals)
+#define DATA unsigned short
+
+/// function used for debug purpose
+#if DEBUG
+#define DEBUG_MESSAGE(strMessage, args...) \
+ if (G.bdebug_messages) { \
+ fprintf(G.logfile_fd, "[%s][%s] - %s\n", \
+ __FILE__, __FUNCTION__, strMessage); \
+ }
+#else
+#define DEBUG_MESSAGE(...) ((void)0)
+#endif
+
+
+/**
+ * open and initialize the framebuffer device.
+ * \param *strfb_device pointer to framebuffer device
+ */
+static void fb_open(char *strfb_device)
+{
+ G.fbfd = xopen(strfb_device, O_RDWR);
+
+ G.theme_file = xfopen(G.strsplash_theme, "r");
+
+ // framebuffer properties
+ xioctl(G.fbfd, FBIOGET_VSCREENINFO, &G.screen_infovar);
+ xioctl(G.fbfd, FBIOGET_FSCREENINFO, &G.screen_infofix);
+
+ // map the device in memory
+ G.addr = mmap(NULL,
+ G.screen_infovar.xres * G.screen_infovar.yres * \
(G.screen_infovar.bits_per_pixel / 8), + PROT_WRITE, MAP_SHARED, G.fbfd, 0);
+
+ if (G.addr == (unsigned char *)-1) {
+#if DEBUG
+ char strMex[30];
+ sprintf(strMex, "can't mmap %s", strfb_device);
+ DEBUG_MESSAGE(strMex);
+#endif
+ exit(EXIT_FAILURE);
+ }
+}
+
+
+/**
+ * draws a rectangle on framebuffer
+ * \param nx1pos,ny1pos upper left position
+ * \param nx2pos,ny2pos down right position
+ * \param nred24,ngreen24,nblue24 rgb colour
+ */
+static void fb_drawrectangle(int nx1pos, int ny1pos, int nx2pos, int ny2pos,
+ unsigned char nred24, unsigned char ngreen24, unsigned char nblue24)
+{
+ int x, y, idx;
+ unsigned char nred16 = (nred24) >> 3; // 5-bit red
+ unsigned char ngreen16 = (ngreen24) >> 2; // 6-bit green
+ unsigned char nblue16 = (nblue24) >> 3; // 5-bit blue
+
+ unsigned nrgb_2bytes = nblue16 + (ngreen16<<5) + (nred16<<(5+6));
+ DATA thispix = nrgb_2bytes;
+
+ // horizontal lines
+ for (x = nx1pos; x <= nx2pos; x++) {
+ idx = (ny1pos * G.screen_infovar.xres + x) * (G.screen_infovar.bits_per_pixel / \
8); + *(DATA *)(G.addr + idx) = thispix;
+
+ idx = (ny2pos * G.screen_infovar.xres + x) * (G.screen_infovar.bits_per_pixel / \
8); + *(DATA *)(G.addr + idx) = thispix;
+ }
+
+ // vertical lines
+ for (y = ny1pos; y <= ny2pos; y++) {
+ idx = (y * G.screen_infovar.xres + nx1pos) * (G.screen_infovar.bits_per_pixel / \
8); + *(DATA *)(G.addr + idx) = thispix;
+
+ idx = (y * G.screen_infovar.xres + nx2pos) * (G.screen_infovar.bits_per_pixel / \
8); + *(DATA *)(G.addr + idx) = thispix;
+ }
+}
+
+
+/**
+ * draws a full rectangle on framebuffer
+ * \param nx1pos,ny1pos upper left position
+ * \param nx2pos,ny2pos down right position
+ * \param nred24,ngreen24,nblue24 rgb colour
+ */
+static void fb_drawfullrectangle(int nx1pos, int ny1pos, int nx2pos, int ny2pos,
+ unsigned char nred24, unsigned char ngreen24, unsigned char nblue24)
+{
+ int x, y, idx;
+ unsigned char nred16 = (nred24) >> 3; // 5-bit red
+ unsigned char ngreen16 = (ngreen24) >> 2; // 6-bit green
+ unsigned char nblue16 = (nblue24) >> 3; // 5-bit blue
+
+ unsigned nrgb_2bytes = nblue16 + (ngreen16<<5) + (nred16<<(5+6));
+ DATA thispix = nrgb_2bytes;
+
+ for (y = ny1pos; y <= ny2pos; y++) {
+ for (x = nx1pos; x <= nx2pos; x++) {
+ idx = (y * G.screen_infovar.xres + x) * (G.screen_infovar.bits_per_pixel / 8);
+ *(DATA *)(G.addr + idx) = thispix;
+ }
+ }
+}
+
+
+/**
+ * draws a progress bar on framebuffer
+ * \param nPercent percentage of loading
+ */
+static void fb_drawprogressbar(unsigned char nPercent)
+{
+ int i;
+
+ fb_drawrectangle(G.nbar_posx, G.nbar_posy,
+ G.nbar_posx + G.nbar_width, G.nbar_posy + G.nbar_height,
+ G.nbar_colr/2, G.nbar_colg/2, G.nbar_colb/2);
+
+ fb_drawfullrectangle(G.nbar_posx + 1, G.nbar_posy + 1,
+ G.nbar_posx + G.nbar_width - 1, G.nbar_posy + G.nbar_height -1,
+ G.nbar_colr, G.nbar_colg, G.nbar_colb);
+
+ for (i = 1; i < (G.nbar_height - 1); i++)
+ fb_drawfullrectangle(G.nbar_posx + 1, G.nbar_posy + i,
+ G.nbar_posx + (G.nbar_width - 1)*nPercent/100,
+ G.nbar_posy + (i+1), 200-(100*(i-1))/(G.nbar_height - 2),
+ 200-(100*(i-1))/(G.nbar_height - 2),
+ 200-(100*(i-1))/(G.nbar_height - 2));
+}
+
+
+/**
+ * draws the theme image
+ */
+static void fb_drawimage(void)
+{
+ uint i, j, x, y, z;
+ char head[256];
+ char s[80];
+ unsigned char pix[3];
+
+ memset(head, 0, sizeof(head));
+
+ rewind(G.theme_file);
+ while (1) {
+ // parse ppm header
+ fgets(s, 80, G.theme_file);
+
+ if (s[0] == '#')
+ continue;
+
+ if (strlen(head) + strlen(s) > 255)
+ exit(3);
+
+ strcat(head, s);
+ if (head[0]!='P' || head[1]!='6')
+ exit(4);
+
+ if (sscanf(head, "P6 %i %i %i", &x, &y, &z) == 3)
+ break;
+// BUG: can go into infinite loop.
+// Imagine a file with the following contents: "P6 123"
+ }
+
+ for (j=0; j<y; j++) {
+ unsigned thispix;
+ for (i = 0; i < x; i++) {
+ int idx;
+ fread(pix, 1, 3, G.theme_file);
+ if (i >= G.screen_infovar.xres)
+ continue;
+ if (j >= G.screen_infovar.yres)
+ continue;
+
+ idx = j * G.screen_infofix.line_length + i*2;
+ thispix = (((short)pix[0] << 8) & 0xf800)
+ | (((short)pix[1] << 3) & 0x07e0)
+ | ((short)pix[2] >> 3);
+
+ *(DATA *)(G.addr + idx) = thispix;
+ }
+ }
+}
+
+
+/**
+ * initializes the application with the data taken from the configuration file.
+ */
+static void init(void)
+{
+ FILE *pinifile;
+ char *buf;
+ static const char const param_value[] ALIGN1 \
+ "DEBUG_MESSAGES\0""SPLASH_THEME\0""BAR_WIDTH\0""BAR_HEIGHT\0" \
+ "BAR_POS_X\0""BAR_POS_Y\0""BAR_R_COL\0""BAR_G_COL\0""BAR_B_COL\0"; +
+ pinifile = xfopen("/etc/bbsplash/bbsplash.ini", "r");
+
+ while ((buf = xmalloc_getline(pinifile)) != NULL) {
+ char *pvalue;
+ int nindex;
+
+ if (*buf == '#') { // it's a comment
+ free(buf);
+ continue;
+ }
+
+ pvalue = strchrnul(buf, '=');
+ if (*pvalue) *pvalue++ = '\0';
+
+ nindex = index_in_strings(param_value, buf);
+
+ switch(nindex) {
+ case 0:
+#if DEBUG
+ G.bdebug_messages = (strcmp(pvalue, "ON") == 0);
+ if (G.bdebug_messages)
+ G.logfile_fd = xfopen("/dev/bbsplash_log", "w");
+#endif
+ break;
+ case 1:
+ // name of the splash theme
+ sprintf(G.strsplash_theme, "/etc/bbsplash/%s", pvalue);
+ break;
+ case 2:
+ // progress bar width
+ G.nbar_width = atoi(pvalue);
+ break;
+ case 3:
+ // progress bar height
+ G.nbar_height = atoi(pvalue);
+ break;
+ case 4:
+ // progress bar orizzontal position
+ G.nbar_posx = atoi(pvalue);
+ break;
+ case 5:
+ // progress bar vertical position
+ G.nbar_posy = atoi(pvalue);
+ break;
+ case 6:
+ // progress bar colour - red component
+ G.nbar_colr = atoi(pvalue);
+ break;
+ case 7:
+ // progress bar colour - green component
+ G.nbar_colg = atoi(pvalue);
+ break;
+ case 8:
+ // progress bar colour - blue component
+ G.nbar_colb = atoi(pvalue);
+ break;
+ }
+
+ free(buf);
+ }
+
+ fclose(pinifile);
+}
+
+
+int bbsplash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int bbsplash_main(int argc, char **argv)
+{
+ int i, fd, len;
+ char buf[255];
+ char *pstrfb_device;
+ char strfb_device[10];
+ bool bCursorOff = false;
+
+ PTR_TO_GLOBALS = xzalloc(sizeof(G));
+
+ // command line option
+ opterr = 0; // disables writing on stderr
+ i = getopt32(argv, "cd:", &pstrfb_device);
+
+ bCursorOff = (i & 0x01);
+
+ if ((i & 0x02) != 0)
+ strcpy(strfb_device, pstrfb_device);
+ else
+ strcpy(strfb_device, "/dev/fb0");
+
+ // initializes the application with the data taken from the configuration file.
+ init();
+
+ // hide the cursor
+ if (bCursorOff) {
+ printf("\E[?25l\n");
+ }
+
+ // change the file mode mask
+ umask(0);
+
+ // open the fifo used for receiving commands
+ mkfifo("/dev/bbsplash_fifo", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+
+ // open the command fifo
+ fd = xopen("/dev/bbsplash_fifo", O_RDWR | O_NOCTTY/* | O_NONBLOCK*/);
+
+ fb_open(strfb_device);
+ fb_drawimage();
+ fb_drawprogressbar(0);
+
+ while(1) {
+ int nVal;
+
+ len = read(fd, buf, 255);
+ if (len == -1) {
+ DEBUG_MESSAGE("error reading the fifo");
+ break;
+ }
+
+ buf[len] = '\0';
+
+ // parse the commands
+ if (strcmp(buf, "exit\n") == 0) {
+ DEBUG_MESSAGE("exit");
+ break;
+ }
+ nVal = atoi(buf);
+ if ((nVal >= 0) && (nVal <= 100)) {
+#if DEBUG
+ char strVal[10];
+ sprintf(strVal, "%d", nVal);
+ DEBUG_MESSAGE(strVal);
+#endif
+ fb_drawprogressbar(nVal);
+ }
+ }
+
+#if DEBUG
+ // closing log file
+ if (G.bdebug_messages)
+ fclose(G.logfile_fd);
+#endif
+
+ // restoring the cursor
+ if (bCursorOff) {
+ printf("\E[?25h\n");
+ }
+
+ // close the fifo
+ close(fd);
+
+ // remove the fifo
+ unlink("/dev/bbsplash_fifo");
+
+ return EXIT_SUCCESS;
+}
diff -urP busybox-1.9.1/miscutils/bbsplash.ini \
busybox-1.9.1_bbsplash/miscutils/bbsplash.ini
--- busybox-1.9.1/miscutils/bbsplash.ini 1970-01-01 01:00:00.000000000 +0100
+++ busybox-1.9.1_bbsplash/miscutils/bbsplash.ini 2008-02-28 14:13:24.000000000 +0100
@@ -0,0 +1,18 @@
+# debug messages: ON or OFF
+DEBUG_MESSAGES=ON
+# splash theme
+SPLASH_THEME=splash.ppm
+# progress bar width
+BAR_WIDTH00
+# progress bar height
+BAR_HEIGHT
+# progress bar orizzontal position
+BAR_POS_X0
+# progress bar vertical position
+BAR_POS_Y00
+# progress bar colour red component
+BAR_R_COL€
+# progress bar colour green component
+BAR_G_COL€
+# progress bar colour blue component
+BAR_B_COL0
diff -urP busybox-1.9.1/miscutils/Config.in \
busybox-1.9.1_bbsplash/miscutils/Config.in
--- busybox-1.9.1/miscutils/Config.in 2008-02-12 17:03:10.000000000 +0100
+++ busybox-1.9.1_bbsplash/miscutils/Config.in 2008-02-28 14:28:06.000000000 +0100
@@ -19,6 +19,27 @@
The bbconfig applet will print the config file with which
busybox was built.
+config BBSPLASH
+ bool "bbsplash"
+ default n
+ help
+ Shows a splash image and a progress bar on framebuffer device.
+ Can be used during the boot phase of a embedded device.
+ If you want logging messages on /dev/bbsplash_log, change the DEBUG define to 1 \
in the source. + Adds 1771 bytes.
+
+ Usage:
+ - pass to the kernel the options 'vga=xxx' to enable the framebuffer with the \
correct resolution + - make the directory '/etc/bbsplash' and put in it the files \
'bbsplash.ini' and the splash image in .ppm format. + - configure the applet by \
editing the .ini file. + - start the applet: $ setsid bbsplash <params>
+ where <params> can be: -c: to hide the cursor; -d /dev/fbn: to select another \
framebuffer device that /dev/fb0 + - if you want run the applet only in presence of \
a kernel parameter (for example bbsplash=on), type: + $ grep -q "bbsplash=on" < \
/proc/cmdline && setsid bbsplash <params> + - send to the /dev/bbsplash_fifo the \
following messages: + (1) the percentage of the boot process.
+ (2) 'exit' in order to kill the applet.
+
config CHRT
bool "chrt"
default n
diff -urP busybox-1.9.1/miscutils/Kbuild busybox-1.9.1_bbsplash/miscutils/Kbuild
--- busybox-1.9.1/miscutils/Kbuild 2008-02-12 17:03:10.000000000 +0100
+++ busybox-1.9.1_bbsplash/miscutils/Kbuild 2008-02-28 14:13:24.000000000 +0100
@@ -7,6 +7,7 @@
lib-y: lib-$(CONFIG_ADJTIMEX) += adjtimex.o
lib-$(CONFIG_BBCONFIG) += bbconfig.o
+lib-$(CONFIG_BBSPLASH) += bbsplash.o
lib-$(CONFIG_CHRT) += chrt.o
lib-$(CONFIG_CROND) += crond.o
lib-$(CONFIG_CRONTAB) += crontab.o
_______________________________________________
busybox mailing list
busybox@busybox.net
http://busybox.net/cgi-bin/mailman/listinfo/busybox
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic