Ok, so working on my theory that the problems were caused by init
interfering with splashy's use of the console I tried patching directfb
to close and reopen the console if it gets a zero length read.

This works in testing, but when I tried it on a real boot things failed
again, strace showed:

549   nanosleep({0, 10},  <unfinished ...>
292   <... read resumed> "", 64)        = 0
292   close(1)                          = 0
292   open("/dev/tty8", O_RDWR|O_NOCTTY) = -1 ENOENT (No such file or directory)
292   open("/dev/vc/8", O_RDWR|O_NOCTTY) = -1 ENOENT (No such file or directory)
292   _exit(0)

I.E. the keyboard reading thread couldn't find the console virtual
terminal, so it's giving up in disgust.

Ponder, ponder, EUREKA!

splashy is started from the initramfs, by the time init zaps the console
the initramfs has been cleaned out, so splashy should be trying to open
the console on the root filesystem.

splashy needs a function to tell it to chroot into the root filesystem
when it has been mounted.  I implemented a splashy_update "chroot dir"
command, and run it from /scripts/init-bottom.

AND IT WORKS!

Summary of changes needed:

1. /etc/init.d/splashy needs to do

        stty -icanon -clocal

    if splashy is already running.

2. directfb needs to be patched to close & reopen the console if it gets
a zero-length read.

3. splashy needs a "chroot" command.

4. the scripts/init-bottom/splashy script needs to tell splashy to do
the chroot.

Patches attached.


--- directfb-1.0.1-orig/systems/fbdev/vt.h	2007-08-07 21:43:00.000000000 +0200
+++ directfb-1.0.1/systems/fbdev/vt.h	2008-04-02 23:14:48.000000000 +0200
@@ -34,7 +34,7 @@
 
 #include <directfb.h>
 
-typedef struct {
+typedef struct VirtualTerminal {
      int fd0;                      /* file descriptor of /dev/tty0 */
      int fd;                       /* file descriptor of /dev/ttyN
                                       where N is the number of the allocated VT,
@@ -56,6 +56,8 @@
      pthread_cond_t   wait;
 
      int              vt_sig;
+
+     DFBResult	     (*method_open) (struct VirtualTerminal *);
 } VirtualTerminal;
 
 /*
--- directfb-1.0.1-orig/systems/fbdev/vt.c	2007-08-07 21:43:00.000000000 +0200
+++ directfb-1.0.1/systems/fbdev/vt.c	2008-04-02 23:07:44.000000000 +0200
@@ -96,6 +96,8 @@
 static void      vt_set_fb( int vt, int fb );
 static void     *vt_thread( DirectThread *thread, void *arg );
 
+static DFBResult vt_open (VirtualTerminal *vt);
+
 DFBResult
 dfb_vt_initialize()
 {
@@ -219,6 +221,8 @@
           return ret;
      }
 
+     dfb_vt->method_open = &vt_open;
+
      dfb_fbdev->vt = dfb_vt;
 
      return DFB_OK;
@@ -439,27 +443,23 @@
 }
 
 static DFBResult
-vt_init_switching()
-{
-     const char cursoroff_str[] = "\033[?1;0;0c";
-     const char blankoff_str[] = "\033[9;0]";
+vt_open (VirtualTerminal *vt) {
+
      char buf[32];
 
      D_DEBUG_AT( VT, "%s()\n", __FUNCTION__ );
 
-     /* FIXME: Opening the device should be moved out of this function. */
-
-     snprintf(buf, 32, "/dev/tty%d", dfb_vt->num);
-     dfb_vt->fd = open( buf, O_RDWR | O_NOCTTY );
-     if (dfb_vt->fd < 0) {
+     snprintf(buf, 32, "/dev/tty%d", vt->num);
+     vt->fd = open( buf, O_RDWR | O_NOCTTY );
+     if (vt->fd < 0) {
           if (errno == ENOENT) {
-               snprintf(buf, 32, "/dev/vc/%d", dfb_vt->num);
-               dfb_vt->fd = open( buf, O_RDWR | O_NOCTTY );
-               if (dfb_vt->fd < 0) {
+               snprintf(buf, 32, "/dev/vc/%d", vt->num);
+               vt->fd = open( buf, O_RDWR | O_NOCTTY );
+               if (vt->fd < 0) {
                     if (errno == ENOENT) {
                          D_PERROR( "DirectFB/core/vt: Couldn't open "
                                     "neither `/dev/tty%d' nor `/dev/vc/%d'!\n",
-                                    dfb_vt->num, dfb_vt->num );
+                                    vt->num, vt->num );
                     }
                     else {
                          D_PERROR( "DirectFB/core/vt: "
@@ -477,7 +477,24 @@
 
      /* attach to the new TTY before doing anything like KDSETMODE with it,
         otherwise we'd get access denied error: */
-     ioctl( dfb_vt->fd, TIOCSCTTY, 0 );
+     if (ioctl( vt->fd, TIOCSCTTY, 0 ) == -1) {
+	  return errno2result (errno);
+     }
+
+     return DFB_OK;
+}
+
+    
+static DFBResult
+vt_init_switching()
+{
+     const char cursoroff_str[] = "\033[?1;0;0c";
+     const char blankoff_str[] = "\033[9;0]";
+     DFBResult res;
+
+     D_DEBUG_AT( VT, "%s()\n", __FUNCTION__ );
+
+     if ((res = vt_open (dfb_vt)) != DFB_OK) return res;
 
      write( dfb_vt->fd, cursoroff_str, sizeof(cursoroff_str) );
      if (dfb_config->kd_graphics) {
--- directfb-1.0.1-orig/inputdrivers/keyboard/keyboard.c	2007-08-07 21:43:00.000000000 +0200
+++ directfb-1.0.1/inputdrivers/keyboard/keyboard.c	2008-04-03 00:32:49.000000000 +0200
@@ -287,6 +287,18 @@
      ioctl( data->vt->fd, KDSKBLED, locks );
 }
 
+static void
+keyboard_set_input (KeyboardData *data)
+{
+     struct termios  ts;
+     ts = data->old_ts;
+     ts.c_cc[VTIME] = 0;
+     ts.c_cc[VMIN] = 1;
+     ts.c_lflag &= ~(ICANON|ECHO|ISIG);
+     ts.c_iflag = 0;
+     tcsetattr( data->vt->fd, TCSAFLUSH, &ts );
+}
+
 static void*
 keyboardEventThread( DirectThread *thread, void *driver_data )
 {
@@ -300,6 +312,13 @@
 
           direct_thread_testcancel( thread );
 
+	  if (readlen == 0) {
+	       /* Maybe our controlling terminal has been stolen by init */
+	       close (data->vt->fd);
+	       if (data->vt->method_open (data->vt) != DFB_OK) break;
+	       keyboard_set_input (data);
+	  }
+
           for (i = 0; i < readlen; i++) {
                DFBInputEvent evt;
 
@@ -351,7 +370,6 @@
                     InputDeviceInfo  *info,
                     void            **driver_data )
 {
-     struct termios  ts;
      KeyboardData   *data;
      FBDev          *dfb_fbdev = dfb_system_data();
 
@@ -369,12 +387,7 @@
 
      tcgetattr( data->vt->fd, &data->old_ts );
 
-     ts = data->old_ts;
-     ts.c_cc[VTIME] = 0;
-     ts.c_cc[VMIN] = 1;
-     ts.c_lflag &= ~(ICANON|ECHO|ISIG);
-     ts.c_iflag = 0;
-     tcsetattr( data->vt->fd, TCSAFLUSH, &ts );
+     keyboard_set_input (data);
 
      tcsetpgrp( data->vt->fd, getpgrp() );
 
--- splashy-0.3.8/src/splashy_functions.c	2008-03-26 18:52:59.000000000 +0100
+++ splashy/src/splashy_functions.c	2008-04-03 16:27:55.000000000 +0200
@@ -367,6 +367,15 @@
         return 0;
 }
 
+gint
+cmd_chroot (void **args)
+{
+	char *dir = args[0];
+	chdir (dir);
+	chroot (dir);
+	return 0;
+}
+
 /*
  * This one is a bit different than the other ones
  * args[0] is prompt string comming from the user
@@ -447,7 +456,9 @@
 	{
         .cmd = "getstring",.handler = cmd_getstring,.args = 1,.specs = "s"},
 	{
-        .cmd = "getpass",.handler = cmd_getpass,.args = 1,.specs = "s"}
+        .cmd = "getpass",.handler = cmd_getpass,.args = 1,.specs = "s"},
+        {
+        .cmd = "chroot",.handler = cmd_chroot,.args = 1,.specs = "s"},
 
 };
 
#!/bin/sh -e

PREREQS=""

prereqs() { echo "$PREREQS"; }

case "$1" in
    prereqs)
    prereqs
    exit 0
    ;;
esac

pidof splashy >/dev/null && /sbin/splashy_update "chroot $rootmnt"

Reply via email to