[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