- Updated to 3.4-rc1.
authorJeff Mahoney <jeffm@suse.com>
Thu, 5 Apr 2012 07:18:14 +0000 (03:18 -0400)
committerJeff Mahoney <jeffm@suse.com>
Mon, 9 Apr 2012 01:36:09 +0000 (21:36 -0400)
  - Eliminated 121 patches.
  - Xen is unavailable.
  - ACPI overrides are unavailable.
  - AppArmor network feature are unavailable.

suse-commit: 3ac7e790b7a41ca1a5d817d1a7732739528266af

100 files changed:
1  2 
Documentation/kernel-parameters.txt
Makefile
arch/arm/include/asm/memory.h
arch/ia64/Kconfig
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/ptrace32.c
arch/powerpc/platforms/chrp/setup.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/xmon/xmon.c
arch/s390/Kconfig
arch/x86/Kconfig
arch/x86/Makefile
arch/x86/include/asm/switch_to.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/apic/bigsmp_32.c
arch/x86/kernel/apic/probe_32.c
arch/x86/kernel/apm_32.c
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/dumpstack.c
arch/x86/kernel/dumpstack_32.c
arch/x86/kernel/dumpstack_64.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kernel/vmlinux.lds.S
arch/x86/kvm/cpuid.c
arch/x86/kvm/svm.c
arch/x86/kvm/x86.c
arch/x86/oprofile/backtrace.c
drivers/acpi/acpica/tbfadt.c
drivers/acpi/thermal.c
drivers/ata/ata_piix.c
drivers/char/Kconfig
drivers/char/Makefile
drivers/char/lp.c
drivers/cpufreq/cpufreq_ondemand.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/input/mouse/Kconfig
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/isdn/mISDN/core.c
drivers/isdn/mISDN/core.h
drivers/isdn/mISDN/socket.c
drivers/md/Kconfig
drivers/md/Makefile
drivers/md/dm-mpath.c
drivers/md/dm-table.c
drivers/md/dm.c
drivers/misc/Kconfig
drivers/net/ethernet/dec/tulip/tulip_core.c
drivers/net/ethernet/ibm/ehea/ehea_main.c
drivers/net/wireless/b43/main.c
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_scan.c
drivers/scsi/sd.c
drivers/scsi/storvsc_drv.c
drivers/tty/n_tty.c
drivers/tty/serial/8250/8250.c
drivers/tty/vt/keyboard.c
drivers/tty/vt/vt.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/bootsplash/bootsplash.c
drivers/video/bootsplash/render.c
drivers/video/console/fbcon.c
fs/btrfs/extent-tree.c
fs/nfs/dir.c
fs/nfs/inode.c
fs/super.c
include/asm-generic/vmlinux.lds.h
include/linux/device.h
include/linux/fb.h
include/linux/kernel.h
include/linux/mm.h
include/linux/module.h
include/linux/nfs_fs.h
include/linux/printk.h
include/linux/sunrpc/sched.h
include/scsi/scsi_device.h
include/scsi/scsi_netlink.h
init/Kconfig
init/main.c
kernel/Kconfig.preempt
kernel/Makefile
kernel/ksysfs.c
kernel/module.c
kernel/printk.c
kernel/sysctl.c
kernel/sysctl_binary.c
lib/Kconfig.debug
mm/page_alloc.c
mm/truncate.c
net/netfilter/Kconfig
net/netfilter/Makefile
net/sunrpc/sched.c
net/sunrpc/xprtsock.c
scripts/Makefile.build
scripts/mod/modpost.c

Simple merge
diff --cc Makefile
Simple merge
Simple merge
Simple merge
Simple merge
  #include <asm/uaccess.h>
  #include <asm/page.h>
  #include <asm/pgtable.h>
- #include <asm/system.h>
+ #include <asm/switch_to.h>
  
 +#include "ppc32.h"
 +
  /*
   * does not yet catch signals sent when the child dies.
   * in exit.c or in signal.c.
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000,4ec45b3..5746248
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,129 +1,139 @@@
+ #ifndef _ASM_X86_SWITCH_TO_H
+ #define _ASM_X86_SWITCH_TO_H
+ struct task_struct; /* one of the stranger aspects of C forward declarations */
+ struct task_struct *__switch_to(struct task_struct *prev,
+                               struct task_struct *next);
+ struct tss_struct;
+ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
+                     struct tss_struct *tss);
+ #ifdef CONFIG_X86_32
+ #ifdef CONFIG_CC_STACKPROTECTOR
+ #define __switch_canary                                                       \
+       "movl %P[task_canary](%[next]), %%ebx\n\t"                      \
+       "movl %%ebx, "__percpu_arg([stack_canary])"\n\t"
+ #define __switch_canary_oparam                                                \
+       , [stack_canary] "=m" (stack_canary.canary)
+ #define __switch_canary_iparam                                                \
+       , [task_canary] "i" (offsetof(struct task_struct, stack_canary))
+ #else /* CC_STACKPROTECTOR */
+ #define __switch_canary
+ #define __switch_canary_oparam
+ #define __switch_canary_iparam
+ #endif        /* CC_STACKPROTECTOR */
+ /*
+  * Saving eflags is important. It switches not only IOPL between tasks,
+  * it also protects other tasks from NT leaking through sysenter etc.
+  */
+ #define switch_to(prev, next, last)                                   \
+ do {                                                                  \
+       /*                                                              \
+        * Context-switching clobbers all registers, so we clobber      \
+        * them explicitly, via unused output variables.                \
+        * (EAX and EBP is not listed because EBP is saved/restored     \
+        * explicitly for wchan access and EAX is the return value of   \
+        * __switch_to())                                               \
+        */                                                             \
+       unsigned long ebx, ecx, edx, esi, edi;                          \
+                                                                       \
+       asm volatile("pushfl\n\t"               /* save    flags */     \
+                    "pushl %%ebp\n\t"          /* save    EBP   */     \
+                    "movl %%esp,%[prev_sp]\n\t"        /* save    ESP   */ \
+                    "movl %[next_sp],%%esp\n\t"        /* restore ESP   */ \
+                    "movl $1f,%[prev_ip]\n\t"  /* save    EIP   */     \
+                    "pushl %[next_ip]\n\t"     /* restore EIP   */     \
+                    __switch_canary                                    \
+                    "jmp __switch_to\n"        /* regparm call  */     \
+                    "1:\t"                                             \
+                    "popl %%ebp\n\t"           /* restore EBP   */     \
+                    "popfl\n"                  /* restore flags */     \
+                                                                       \
+                    /* output parameters */                            \
+                    : [prev_sp] "=m" (prev->thread.sp),                \
+                      [prev_ip] "=m" (prev->thread.ip),                \
+                      "=a" (last),                                     \
+                                                                       \
+                      /* clobbered output registers: */                \
+                      "=b" (ebx), "=c" (ecx), "=d" (edx),              \
+                      "=S" (esi), "=D" (edi)                           \
+                                                                       \
+                      __switch_canary_oparam                           \
+                                                                       \
+                      /* input parameters: */                          \
+                    : [next_sp]  "m" (next->thread.sp),                \
+                      [next_ip]  "m" (next->thread.ip),                \
+                                                                       \
+                      /* regparm parameters for __switch_to(): */      \
+                      [prev]     "a" (prev),                           \
+                      [next]     "d" (next)                            \
+                                                                       \
+                      __switch_canary_iparam                           \
+                                                                       \
+                    : /* reloaded segment registers */                 \
+                       "memory");                                      \
+ } while (0)
+ #else /* CONFIG_X86_32 */
+ /* frame pointer must be last for get_wchan */
+ #define SAVE_CONTEXT    "pushf ; pushq %%rbp ; movq %%rsi,%%rbp\n\t"
+ #define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp ; popf\t"
+ #define __EXTRA_CLOBBER  \
+       , "rcx", "rbx", "rdx", "r8", "r9", "r10", "r11", \
+         "r12", "r13", "r14", "r15"
+ #ifdef CONFIG_CC_STACKPROTECTOR
+ #define __switch_canary                                                         \
+       "movq %P[task_canary](%%rsi),%%r8\n\t"                            \
+       "movq %%r8,"__percpu_arg([gs_canary])"\n\t"
+ #define __switch_canary_oparam                                                  \
+       , [gs_canary] "=m" (irq_stack_union.stack_canary)
+ #define __switch_canary_iparam                                                  \
+       , [task_canary] "i" (offsetof(struct task_struct, stack_canary))
+ #else /* CC_STACKPROTECTOR */
+ #define __switch_canary
+ #define __switch_canary_oparam
+ #define __switch_canary_iparam
+ #endif        /* CC_STACKPROTECTOR */
++/* The stack unwind code needs this but it pollutes traces otherwise */
++#ifdef CONFIG_UNWIND_INFO
++#define THREAD_RETURN_SYM \
++      ".globl thread_return\n" \
++      "thread_return:\n\t"
++#else
++#define THREAD_RETURN_SYM
++#endif
++
+ /* Save restore flags to clear handle leaking NT */
+ #define switch_to(prev, next, last) \
+       asm volatile(SAVE_CONTEXT                                         \
+            "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */       \
+            "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */    \
+            "call __switch_to\n\t"                                       \
++           THREAD_RETURN_SYM                                            \
+            "movq "__percpu_arg([current_task])",%%rsi\n\t"              \
+            __switch_canary                                              \
+            "movq %P[thread_info](%%rsi),%%r8\n\t"                       \
+            "movq %%rax,%%rdi\n\t"                                       \
+            "testl  %[_tif_fork],%P[ti_flags](%%r8)\n\t"                 \
+            "jnz   ret_from_fork\n\t"                                    \
+            RESTORE_CONTEXT                                              \
+            : "=a" (last)                                                \
+              __switch_canary_oparam                                     \
+            : [next] "S" (next), [prev] "D" (prev),                      \
+              [threadrsp] "i" (offsetof(struct task_struct, thread.sp)), \
+              [ti_flags] "i" (offsetof(struct thread_info, flags)),      \
+              [_tif_fork] "i" (_TIF_FORK),                               \
+              [thread_info] "i" (offsetof(struct task_struct, stack)),   \
+              [current_task] "m" (current_task)                          \
+              __switch_canary_iparam                                     \
+            : "memory", "cc" __EXTRA_CLOBBER)
+ #endif /* CONFIG_X86_32 */
+ #endif /* _ASM_X86_SWITCH_TO_H */
@@@ -1367,23 -1350,7 +1350,22 @@@ static int __init dmi_ignore_irq0_timer
        }
        return 0;
  }
- #endif
  
 +static int __init force_acpi_rsdt(const struct dmi_system_id *d)
 +{
 +      if (!acpi_force) {
 +              printk(KERN_NOTICE "%s detected: force use of acpi=rsdt\n",
 +                     d->ident);
 +              acpi_rsdt_forced = 1;
 +      } else {
 +              printk(KERN_NOTICE
 +                     "Warning: acpi=force overrules DMI blacklist: "
 +                     "acpi=rsdt\n");
 +      }
 +      return 0;
 +
 +}
 +
  /*
   * If your system is blacklisted here, but you find that acpi=force
   * works for you, please contact linux-acpi@vger.kernel.org
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -1222,41 -1260,7 +1265,41 @@@ ENTRY(call_softirq
        CFI_ENDPROC
  END(call_softirq)
  
 +#ifdef CONFIG_STACK_UNWIND
 +ENTRY(arch_unwind_init_running)
 +      CFI_STARTPROC
 +      movq    %r15, R15(%rdi)
 +      movq    %r14, R14(%rdi)
 +      xchgq   %rsi, %rdx
 +      movq    %r13, R13(%rdi)
 +      movq    %r12, R12(%rdi)
 +      xorl    %eax, %eax
 +      movq    %rbp, RBP(%rdi)
 +      movq    %rbx, RBX(%rdi)
 +      movq    (%rsp), %r9
 +      xchgq   %rdx, %rcx
 +      movq    %rax, R11(%rdi)
 +      movq    %rax, R10(%rdi)
 +      movq    %rax, R9(%rdi)
 +      movq    %rax, R8(%rdi)
 +      movq    %rax, RAX(%rdi)
 +      movq    %rax, RCX(%rdi)
 +      movq    %rax, RDX(%rdi)
 +      movq    %rax, RSI(%rdi)
 +      movq    %rax, RDI(%rdi)
 +      movq    %rax, ORIG_RAX(%rdi)
 +      movq    %r9, RIP(%rdi)
 +      leaq    8(%rsp), %r9
 +      movq    $__KERNEL_CS, CS(%rdi)
 +      movq    %rax, EFLAGS(%rdi)
 +      movq    %r9, RSP(%rdi)
 +      movq    $__KERNEL_DS, SS(%rdi)
 +      jmpq    *%rcx
 +      CFI_ENDPROC
 +END(arch_unwind_init_running)
 +#endif
 +
- #ifdef CONFIG_PARAVIRT_XEN
+ #ifdef CONFIG_XEN
  zeroentry xen_hypervisor_callback xen_do_hypervisor_callback
  
  /*
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -24,9 -27,9 +27,10 @@@ obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE)  += 
  obj-$(CONFIG_TOUCHSCREEN_GUNZE)               += gunze.o
  obj-$(CONFIG_TOUCHSCREEN_EETI)                += eeti_ts.o
  obj-$(CONFIG_TOUCHSCREEN_ELO)         += elo.o
 +obj-$(CONFIG_TOUCHSCREEN_ELOUSB)      += elousb.o
  obj-$(CONFIG_TOUCHSCREEN_EGALAX)      += egalax_ts.o
  obj-$(CONFIG_TOUCHSCREEN_FUJITSU)     += fujitsu_ts.o
+ obj-$(CONFIG_TOUCHSCREEN_ILI210X)     += ili210x.o
  obj-$(CONFIG_TOUCHSCREEN_INEXIO)      += inexio.o
  obj-$(CONFIG_TOUCHSCREEN_INTEL_MID)   += intel-mid-touch.o
  obj-$(CONFIG_TOUCHSCREEN_LPC32XX)     += lpc32xx_ts.o
Simple merge
Simple merge
@@@ -696,24 -692,20 +696,24 @@@ base_sock_ioctl(struct socket *sock, un
                        err = -ENODEV;
                break;
        case IMSETDEVNAME:
-               {
-                       struct mISDN_devrename dn;
-                       if(!capable(CAP_SYS_ADMIN)
-                               && (misdn_permitted_gid != current_gid())
-                               && (!in_group_p(misdn_permitted_gid)))
-                                       return -EPERM;
-                       if (copy_from_user(&dn, (void __user *)arg,
-                           sizeof(dn))) {
-                               err = -EFAULT;
-                               break;
-                       }
-                       dev = get_mdevice(dn.id);
-                       if (dev)
-                               err = device_rename(&dev->dev, dn.name);
-                       else
-                               err = -ENODEV;
+       {
+               struct mISDN_devrename dn;
++              if(!capable(CAP_SYS_ADMIN)
++                      && (misdn_permitted_gid != current_gid())
++                      && (!in_group_p(misdn_permitted_gid)))
++                              return -EPERM;
+               if (copy_from_user(&dn, (void __user *)arg,
+                                  sizeof(dn))) {
+                       err = -EFAULT;
+                       break;
                }
-               break;
+               dev = get_mdevice(dn.id);
+               if (dev)
+                       err = device_rename(&dev->dev, dn.name);
+               else
+                       err = -ENODEV;
+       }
+       break;
        default:
                err = -EINVAL;
        }
@@@ -359,23 -358,9 +359,23 @@@ config DM_DELA
  
        If unsure, say N.
  
 +config DM_REGION_HASH_LOG
 +      tristate
 +      default n
 +
 +config DM_RAID45
 +      tristate "RAID 4/5 target (EXPERIMENTAL)"
 +      depends on BLK_DEV_DM && EXPERIMENTAL
 +      select ASYNC_XOR
 +      select DM_REGION_HASH_LOG
 +      ---help---
 +      A target that supports RAID4 and RAID5 mappings.
 +
 +      If unsure, say N.
 +
  config DM_UEVENT
-       bool "DM uevents (EXPERIMENTAL)"
-       depends on BLK_DEV_DM && EXPERIMENTAL
+       bool "DM uevents"
+       depends on BLK_DEV_DM
        ---help---
        Generate udev events for DM events.
  
@@@ -43,7 -42,7 +43,8 @@@ obj-$(CONFIG_DM_LOG_USERSPACE)        += dm-lo
  obj-$(CONFIG_DM_ZERO)         += dm-zero.o
  obj-$(CONFIG_DM_RAID) += dm-raid.o
  obj-$(CONFIG_DM_THIN_PROVISIONING)    += dm-thin-pool.o
+ obj-$(CONFIG_DM_VERITY)               += dm-verity.o
 +obj-$(CONFIG_DM_RAID45)               += dm-raid45.o dm-memcache.o
  
  ifeq ($(CONFIG_DM_UEVENT),y)
  dm-mod-objs                   += dm-uevent.o
Simple merge
Simple merge
diff --cc drivers/md/dm.c
Simple merge
Simple merge
Simple merge
@@@ -2072,11 -2061,8 +2066,8 @@@ static struct vio_driver ibmvscsi_drive
        .probe = ibmvscsi_probe,
        .remove = ibmvscsi_remove,
        .get_desired_dma = ibmvscsi_get_desired_dma,
-       .driver = {
-               .name = IBMVSCSI_PROC_NAME,
-               .owner = THIS_MODULE,
-               .pm = &ibmvscsi_pm_ops,
-       }
 -      .name = "ibmvscsi",
++      .name = IBMVSCSI_PROC_NAME,
+       .pm = &ibmvscsi_pm_ops,
  };
  
  static struct srp_function_template ibmvscsi_transport_functions = {
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
  #include <linux/uaccess.h>
  #include <linux/module.h>
  
 +#include <linux/bootsplash.h>
  
- #include <asm/system.h>
  /* number of characters left in xmit buffer before select has we have room */
  #define WAKEUP_CHARS 256
  
@@@ -1390,11 -1368,7 +1370,11 @@@ serial8250_rx_chars(struct uart_8250_po
  
        do {
                if (likely(lsr & UART_LSR_DR))
 +              {
-                       ch = serial_inp(up, UART_RX);
+                       ch = serial_in(up, UART_RX);
 +                      if (arch_8250_sysrq_via_ctrl_o(ch, &up->port))
 +                              goto ignore_char;
 +              }
                else
                        /*
                         * Intel 82571 has a Serial Over Lan device that will
Simple merge
Simple merge
@@@ -2422,8 -2424,16 +2424,20 @@@ if FB || SGI_NEWPORT_CONSOL
        source "drivers/video/logo/Kconfig"
  endif
  
 +if FB
 +      source "drivers/video/bootsplash/Kconfig"
 +endif
 +
+ config FB_SH_MOBILE_MERAM
+       tristate "SuperH Mobile MERAM read ahead support"
+       depends on (SUPERH || ARCH_SHMOBILE)
+       select GENERIC_ALLOCATOR
+       ---help---
+         Enable MERAM support for the SuperH controller.
+         This will allow for caching of the framebuffer to provide more
+         reliable access under heavy main memory bus traffic situations.
+         Up to 4 memory channels can be configured, allowing 4 RGB or
+         2 YCbCr framebuffers to be configured.
  endmenu
@@@ -14,8 -14,9 +14,10 @@@ fb-objs                           := $(
  obj-$(CONFIG_VT)                += console/
  obj-$(CONFIG_LOGO)              += logo/
  obj-y                           += backlight/
 +obj-$(CONFIG_BOOTSPLASH)        += bootsplash/
  
+ obj-$(CONFIG_EXYNOS_VIDEO)     += exynos/
  obj-$(CONFIG_FB_CFB_FILLRECT)  += cfbfillrect.o
  obj-$(CONFIG_FB_CFB_COPYAREA)  += cfbcopyarea.o
  obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o
index 63d72f8,0000000..d96edce
mode 100644,000000..100644
--- /dev/null
@@@ -1,2493 -1,0 +1,2492 @@@
 +/*
 + *           linux/drivers/video/bootsplash/bootsplash.c -
 + *                 splash screen handling functions.
 + *
 + *    (w) 2001-2004 by Volker Poplawski, <volker@poplawski.de>,
 + *                    Stefan Reinauer, <stepan@suse.de>,
 + *                    Steffen Winterfeldt, <snwint@suse.de>,
 + *                    Michael Schroeder <mls@suse.de>
 + *        2009-2011 Egbert Eich <eich@suse.de>
 + *
 + *        Ideas & SuSE screen work by Ken Wimer, <wimer@suse.de>
 + *
 + *  For more information on this code check http://www.bootsplash.org/
 + */
 +
 +#include <linux/module.h>
 +#include <linux/types.h>
 +#include <linux/fb.h>
 +#include <linux/vt_kern.h>
 +#include <linux/vmalloc.h>
 +#include <linux/unistd.h>
 +#include <linux/syscalls.h>
 +#include <linux/console.h>
 +#include <linux/workqueue.h>
 +#include <linux/slab.h>
 +
 +#include <asm/irq.h>
- #include <asm/system.h>
 +
 +#include "../console/fbcon.h"
 +#include <linux/bootsplash.h>
 +#include "decode-jpg.h"
 +
 +#ifndef DEBUG
 +# define SPLASH_DEBUG(fmt, args...)
 +#else
 +# define SPLASH_DEBUG(fmt, args...) \
 +      printk(KERN_WARNING "%s: " fmt "\n", __func__, ##args)
 +#endif
 +extern signed char con2fb_map[MAX_NR_CONSOLES];
 +
 +#define SPLASH_VERSION "3.2.0-2010/03/31"
 +
 +/* These errors have to match fbcon-jpegdec.h */
 +static unsigned char *jpg_errors[] = {
 +      "no SOI found",
 +      "not 8 bit",
 +      "height mismatch",
 +      "width mismatch",
 +      "bad width or height",
 +      "too many COMPPs",
 +      "illegal HV",
 +      "quant table selector",
 +      "picture is not YCBCR 221111",
 +      "unknow CID in scan",
 +      "dct not sequential",
 +      "wrong marker",
 +      "no EOI",
 +      "bad tables",
 +      "depth mismatch",
 +      "scale error",
 +      "out of memory"
 +};
 +
 +static int splash_usesilent;
 +static unsigned long splash_default = 0xf01;
 +
 +static int jpeg_get(unsigned char *buf, unsigned char *pic,
 +                  int width, int height, enum splash_color_format cf,
 +                  struct jpeg_decdata *decdata);
 +static int splash_look_for_jpeg(struct vc_data *vc, int width, int height);
 +
 +static int __init splash_setup(char *options)
 +{
 +      splash_usesilent = 0;
 +
 +      if (!strncmp("silent", options, 6)) {
 +              printk(KERN_INFO "bootsplash: silent mode.\n");
 +              splash_usesilent = 1;
 +              /* skip "silent," */
 +              if (strlen(options) == 6)
 +                      return 0;
 +              options += 7;
 +      }
 +      if (!strncmp("verbose", options, 7)) {
 +              printk(KERN_INFO "bootsplash: verbose mode.\n");
 +              splash_usesilent = 0;
 +              if (strlen(options) == 7)
 +                      return 0;
 +              options += 8;
 +      }
 +      if (strict_strtoul(options, 0, &splash_default) == -EINVAL)
 +              splash_default = 0;
 +
 +      return 0;
 +}
 +
 +__setup("splash=", splash_setup);
 +
 +
 +static int splash_hasinter(unsigned char *buf, int num)
 +{
 +      unsigned char *bufend = buf + num * 12;
 +      while (buf < bufend) {
 +              if (buf[1] > 127)               /* inter? */
 +                      return 1;
 +              buf += buf[3] > 127 ? 24 : 12;  /* blend? */
 +      }
 +      return 0;
 +}
 +
 +static int boxextract(unsigned char *buf, unsigned short *dp,
 +                    unsigned char *cols, int *blendp)
 +{
 +      dp[0] = buf[0] | buf[1] << 8;
 +      dp[1] = buf[2] | buf[3] << 8;
 +      dp[2] = buf[4] | buf[5] << 8;
 +      dp[3] = buf[6] | buf[7] << 8;
 +      *(unsigned int *)(cols + 0) =
 +              *(unsigned int *)(cols + 4) =
 +              *(unsigned int *)(cols + 8) =
 +              *(unsigned int *)(cols + 12) = *(unsigned int *)(buf + 8);
 +      if (dp[1] > 32767) {
 +              dp[1] = ~dp[1];
 +              *(unsigned int *)(cols + 4) = *(unsigned int *)(buf + 12);
 +              *(unsigned int *)(cols + 8) = *(unsigned int *)(buf + 16);
 +              *(unsigned int *)(cols + 12) = *(unsigned int *)(buf + 20);
 +              *blendp = 1;
 +              return 24;
 +      }
 +      return 12;
 +}
 +
 +static void boxit(unsigned char *pic, int bytes, unsigned char *buf, int num,
 +                int percent, int xoff, int yoff, int overpaint,
 +                enum splash_color_format cf)
 +{
 +      int x, y, p, doblend, r, g, b, a, add;
 +      unsigned int i = 0;
 +      unsigned short data1[4];
 +      unsigned char cols1[16];
 +      unsigned short data2[4];
 +      unsigned char cols2[16];
 +      unsigned char *bufend;
 +      union pt picp;
 +      unsigned int stipple[32], sti, stin, stinn, stixs, stixe, stiys, stiye;
 +      int xs, xe, ys, ye, xo, yo;
 +      int octpp = splash_octpp(cf);
 +
 +      SPLASH_DEBUG();
 +      if (num == 0 || percent < -1)
 +              return;
 +      bufend = buf + num * 12;
 +      stipple[0] = 0xffffffff;
 +      stin = 1;
 +      stinn = 0;
 +      stixs = stixe = 0;
 +      stiys = stiye = 0;
 +      while (buf < bufend) {
 +              doblend = 0;
 +              buf += boxextract(buf, data1, cols1, &doblend);
 +              if (data1[0] == 32767 && data1[1] == 32767) {
 +                      /* box stipple */
 +                      if (stinn == 32)
 +                              continue;
 +                      if (stinn == 0) {
 +                              stixs = data1[2];
 +                              stixe = data1[3];
 +                              stiys = stiye = 0;
 +                      } else if (stinn == 4) {
 +                              stiys = data1[2];
 +                              stiye = data1[3];
 +                      }
 +                      stipple[stinn++] = (cols1[0]  << 24) |
 +                              (cols1[1]  << 16) |
 +                              (cols1[2]  << 8)  |
 +                              cols1[3] ;
 +                      stipple[stinn++] = (cols1[4]  << 24) |
 +                              (cols1[5]  << 16) |
 +                              (cols1[6]  << 8)  |
 +                              cols1[7] ;
 +                      stipple[stinn++] = (cols1[8]  << 24) |
 +                              (cols1[9]  << 16) |
 +                              (cols1[10] << 8)  |
 +                              cols1[11] ;
 +                      stipple[stinn++] = (cols1[12] << 24) |
 +                              (cols1[13] << 16) |
 +                              (cols1[14] << 8)  |
 +                              cols1[15] ;
 +                      stin = stinn;
 +                      continue;
 +              }
 +              stinn = 0;
 +              if (data1[0] > 32767)
 +                      buf += boxextract(buf, data2, cols2, &doblend);
 +              if (data1[0] == 32767 && data1[1] == 32766) {
 +                      /* box copy */
 +                      i = 12 * (short)data1[3];
 +                      doblend = 0;
 +                      i += boxextract(buf + i, data1, cols1, &doblend);
 +                      if (data1[0] > 32767)
 +                              boxextract(buf + i, data2, cols2, &doblend);
 +              }
 +              if (data1[0] == 32767)
 +                      continue;
 +              if (data1[2] > 32767) {
 +                      if (overpaint)
 +                              continue;
 +                      data1[2] = ~data1[2];
 +              }
 +              if (data1[3] > 32767) {
 +                      if (percent == 65536)
 +                              continue;
 +                      data1[3] = ~data1[3];
 +              }
 +              if (data1[0] > 32767) {
 +                      if (percent < 0)
 +                              continue;
 +                      data1[0] = ~data1[0];
 +                      for (i = 0; i < 4; i++)
 +                              data1[i] = (data1[i] * (65536 - percent)
 +                                          + data2[i] * percent) >> 16;
 +                      for (i = 0; i < 16; i++)
 +                              cols1[i] = (cols1[i] * (65536 - percent)
 +                                          + cols2[i] * percent) >> 16;
 +              }
 +              *(unsigned int *)cols2 = *(unsigned int *)cols1;
 +              a = cols2[3];
 +              if (a == 0 && !doblend)
 +                      continue;
 +
 +              if (stixs >= 32768) {
 +                      xo = xs = (stixs ^ 65535) + data1[0];
 +                      xe = stixe ? stixe + data1[0] : data1[2];
 +              } else if (stixe >= 32768) {
 +                      xs = stixs ? data1[2] - stixs : data1[0];
 +                      xe = data1[2] - (stixe ^ 65535);
 +                      xo = xe + 1;
 +              } else {
 +                      xo = xs = stixs;
 +                      xe = stixe ? stixe : data1[2];
 +              }
 +              if (stiys >= 32768) {
 +                      yo = ys = (stiys ^ 65535) + data1[1];
 +                      ye = stiye ? stiye + data1[1] : data1[3];
 +              } else if (stiye >= 32768) {
 +                      ys = stiys ? data1[3] - stiys : data1[1];
 +                      ye = data1[3] - (stiye ^ 65535);
 +                      yo = ye + 1;
 +              } else {
 +                      yo = ys = stiys;
 +                      ye = stiye ? stiye : data1[3];
 +              }
 +              xo = 32 - (xo & 31);
 +              yo = stin - (yo % stin);
 +              if (xs < data1[0])
 +                      xs = data1[0];
 +              if (xe > data1[2])
 +                      xe = data1[2];
 +              if (ys < data1[1])
 +                      ys = data1[1];
 +              if (ye > data1[3])
 +                      ye = data1[3];
 +
 +              for (y = ys; y <= ye; y++) {
 +                      sti = stipple[(y + yo) % stin];
 +                      x = (xs + xo) & 31;
 +                      if (x)
 +                              sti = (sti << x) | (sti >> (32 - x));
 +                      if (doblend) {
 +                              p = data1[3] - data1[1];
 +                              if (p != 0)
 +                                      p = ((y - data1[1]) << 16) / p;
 +                              for (i = 0; i < 8; i++)
 +                                      cols2[i + 8] = (cols1[i] * (65536 - p)
 +                                                      + cols1[i + 8] * p)
 +                                              >> 16;
 +                      }
 +                      add = (xs & 1);
 +                      add ^= (add ^ y) & 1 ? 1 : 3; /*2x2 ordered dithering*/
 +                      picp.ub = (pic + (xs + xoff) * octpp
 +                                 + (y + yoff) * bytes);
 +                      for (x = xs; x <= xe; x++) {
 +                              if (!(sti & 0x80000000)) {
 +                                      sti <<= 1;
 +                                      switch (octpp) {
 +                                      case 2:
 +                                              picp.us++;
 +                                              break;
 +                                      case 3:
 +                                              picp.ub += 3;
 +                                              break;
 +                                      case 4:
 +                                              picp.ul++;
 +                                              break;
 +                                      }
 +                                      add ^= 3;
 +                                      continue;
 +                              }
 +                              sti = (sti << 1) | 1;
 +                              if (doblend) {
 +                                      p = data1[2] - data1[0];
 +                                      if (p != 0)
 +                                              p = ((x - data1[0]) << 16) / p;
 +                                      for (i = 0; i < 4; i++)
 +                                              cols2[i] = (cols2[i + 8] * (65536 - p)
 +                                                          + cols2[i + 12] * p)
 +                                                      >> 16;
 +                                      a = cols2[3];
 +                              }
 +                              r = cols2[0];
 +                              g = cols2[1];
 +                              b = cols2[2];
 +#define CLAMP(x) ((x) >= 256 ? 255 : (x))
 +#define BLEND(x, v, a) ((x * (255 - a) + v * a) / 255)
 +                              switch (cf) {
 +                              case SPLASH_DEPTH_15:
 +                                      if (a != 255) {
 +                                              i = *picp.us;
 +                                              r = BLEND((i>>7 & 0xf8), r, a);
 +                                              g = BLEND((i>>2 & 0xf8), g, a);
 +                                              b = BLEND((i<<3 & 0xf8), b, a);
 +                                      }
 +                                      r += add * 2 + 1;
 +                                      g += add;
 +                                      b += add * 2 + 1;
 +                                      i =     ((CLAMP(r) & 0xf8) <<  7) |
 +                                              ((CLAMP(g) & 0xf8) <<  2) |
 +                                              ((CLAMP(b))        >>  3);
 +                                      *(picp.us++) = i;
 +                                      break;
 +                              case SPLASH_DEPTH_16:
 +                                      if (a != 255) {
 +                                              i = *picp.us;
 +                                              r = BLEND((i>>8 & 0xf8), r, a);
 +                                              g = BLEND((i>>3 & 0xfc), g, a);
 +                                              b = BLEND((i<<3 & 0xf8), b, a);
 +                                      }
 +                                      r += add * 2 + 1;
 +                                      g += add;
 +                                      b += add * 2 + 1;
 +                                              i = ((CLAMP(r) & 0xf8) <<  8) |
 +                                                  ((CLAMP(g) & 0xfc) <<  3) |
 +                                                  ((CLAMP(b))        >>  3);
 +                                      *(picp.us++) = i;
 +                                      break;
 +                              case SPLASH_DEPTH_24_PACKED:
 +                                      if (a != 255) {
 +                                              i = *picp.ub;
 +                                              r = BLEND((i & 0xff), r, a);
 +                                              i = *(picp.ub + 1);
 +                                              g = BLEND((i & 0xff), g, a);
 +                                              i = *(picp.ub + 2);
 +                                              b = BLEND((i & 0xff), b, a);
 +                                      }
 +                                      *(picp.ub++) = CLAMP(r);
 +                                      *(picp.ub++) = CLAMP(g);
 +                                      *(picp.ub++) = CLAMP(b);
 +                                      break;
 +                              case SPLASH_DEPTH_24:
 +                                      if (a != 255) {
 +                                              i = *picp.ul;
 +                                              r = BLEND((i>>16 & 0xff), r, a);
 +                                              g = BLEND((i>>8  & 0xff), g, a);
 +                                              b = BLEND((i     & 0xff), b, a);
 +                                      }
 +                                      i = ((CLAMP(r) << 16)
 +                                           | (CLAMP(g) << 8)
 +                                           | (CLAMP(b)));
 +                                      *(picp.ul++) = i;
 +                                      break;
 +                              default:
 +                                      break;
 +                              }
 +                              add ^= 3;
 +                      }
 +              }
 +      }
 +}
 +
 +static void box_offsets(unsigned char *buf, int num,
 +                      int screen_w, int screen_h, int pic_w, int pic_h,
 +                      int *x_off, int *y_off)
 +{
 +      int a, doblend;
 +      int x_min = pic_w, x_max = 0;
 +      int y_min = pic_h, y_max = 0;
 +      unsigned int i = 0;
 +      unsigned short data1[4];
 +      unsigned char cols1[16];
 +      unsigned short data2[4];
 +      unsigned char cols2[16];
 +      unsigned char *bufend;
 +      unsigned int stin, stinn, stixs, stixe, stiys, stiye;
 +      int xs, xe, ys, ye;
 +
 +      SPLASH_DEBUG();
 +
 +      if ((screen_w == pic_w && screen_h == pic_h) || num == 0)
 +              *x_off = *y_off = 0;
 +
 +      bufend = buf + num * 12;
 +      stin = 1;
 +      stinn = 0;
 +      stixs = stixe = 0;
 +      stiys = stiye = 0;
 +
 +      while (buf < bufend) {
 +              doblend = 0;
 +              buf += boxextract(buf, data1, cols1, &doblend);
 +              if (data1[0] == 32767 && data1[1] == 32767) {
 +                      /* box stipple */
 +                      if (stinn == 32)
 +                              continue;
 +                      if (stinn == 0) {
 +                              stixs = data1[2];
 +                              stixe = data1[3];
 +                              stiys = stiye = 0;
 +                      } else if (stinn == 4) {
 +                              stiys = data1[2];
 +                              stiye = data1[3];
 +                      }
 +                      stin = stinn;
 +                      continue;
 +              }
 +              stinn = 0;
 +              if (data1[0] > 32767)
 +                      buf += boxextract(buf, data2, cols2, &doblend);
 +              if (data1[0] == 32767 && data1[1] == 32766) {
 +                      /* box copy */
 +                      i = 12 * (short)data1[3];
 +                      doblend = 0;
 +                      i += boxextract(buf + i, data1, cols1, &doblend);
 +                      if (data1[0] > 32767)
 +                              boxextract(buf + i, data2, cols2, &doblend);
 +              }
 +              if (data1[0] == 32767)
 +                      continue;
 +              if (data1[2] > 32767)
 +                      data1[2] = ~data1[2];
 +              if (data1[3] > 32767)
 +                      data1[3] = ~data1[3];
 +              if (data1[0] > 32767) {
 +                      data1[0] = ~data1[0];
 +                      for (i = 0; i < 4; i++)
 +                              data1[i] = (data1[i] * (65536 - 1)
 +                                          + data2[i] * 1) >> 16;
 +              }
 +              *(unsigned int *)cols2 = *(unsigned int *)cols1;
 +              a = cols2[3];
 +              if (a == 0 && !doblend)
 +                      continue;
 +
 +              if (stixs >= 32768) {
 +                      xs = (stixs ^ 65535) + data1[0];
 +                      xe = stixe ? stixe + data1[0] : data1[2];
 +              } else if (stixe >= 32768) {
 +                      xs = stixs ? data1[2] - stixs : data1[0];
 +                      xe = data1[2] - (stixe ^ 65535);
 +              } else {
 +                      xs = stixs;
 +                      xe = stixe ? stixe : data1[2];
 +              }
 +              if (stiys >= 32768) {
 +                      ys = (stiys ^ 65535) + data1[1];
 +                      ye = stiye ? stiye + data1[1] : data1[3];
 +              } else if (stiye >= 32768) {
 +                      ys = stiys ? data1[3] - stiys : data1[1];
 +                      ye = data1[3] - (stiye ^ 65535);
 +              } else {
 +                      ys = stiys;
 +                      ye = stiye ? stiye : data1[3];
 +              }
 +              if (xs < data1[0])
 +                      xs = data1[0];
 +              if (xe > data1[2])
 +                      xe = data1[2];
 +              if (ys < data1[1])
 +                      ys = data1[1];
 +              if (ye > data1[3])
 +                      ye = data1[3];
 +
 +              if (xs < x_min)
 +                      x_min = xs;
 +              if (xe > x_max)
 +                      x_max = xe;
 +              if (ys < y_min)
 +                      y_min = ys;
 +              if (ye > y_max)
 +                      y_max = ye;
 +      }
 +      {
 +              int x_center = (x_min + x_max) / 2;
 +              int y_center = (y_min + y_max) / 2;
 +
 +              if (screen_w == pic_w)
 +                      *x_off = 0;
 +              else {
 +                      if (x_center < (pic_w + pic_w / 5) >> 1 &&
 +                          x_center > (pic_w - pic_w / 5) >> 1) {
 +                              *x_off = (screen_w - pic_w) >> 1;
 +                      } else {
 +                              int x = x_center * screen_w / pic_w;
 +                              *x_off = x - x_center;
 +                              if (x_min + *x_off < 0)
 +                                      *x_off = 0;
 +                              if (x_max + *x_off > screen_w)
 +                                      *x_off = screen_w - pic_w;
 +                      }
 +              }
 +              if (screen_h == pic_h)
 +                      *y_off = 0;
 +              else {
 +                      if (y_center < (pic_h + pic_h / 5) >> 1 &&
 +                          y_center > (pic_h - pic_h / 5) >> 1)
 +                              *y_off = (screen_h - pic_h) >> 1;
 +                      else {
 +                              int x = y_center * screen_h / pic_h;
 +                              *y_off = x - y_center;
 +                              if (y_min + *y_off < 0)
 +                                      *y_off = 0;
 +                              if (y_max + *x_off > screen_h)
 +                                      *y_off = screen_h - pic_h;
 +                      }
 +              }
 +      }
 +}
 +
 +static int splash_check_jpeg(unsigned char *jpeg,
 +                           int width, int height)
 +{
 +      int size, err;
 +      unsigned char *mem;
 +      struct jpeg_decdata *decdata; /* private decoder data */
 +
 +
 +      size = ((width + 15) & ~15) * ((height + 15) & ~15) * 2;
 +      mem = vmalloc(size);
 +      if (!mem) {
 +              printk(KERN_INFO "bootsplash: no memory for decoded picture.\n");
 +              return -1;
 +      }
 +      decdata = vmalloc(sizeof(*decdata));
 +      if (!decdata) {
 +              printk(KERN_INFO "bootsplash: not enough memory.\n");
 +              vfree(mem);
 +              return -1;
 +      }
 +      /* test decode: use fixed depth of 16 */
 +      err = jpeg_decode(jpeg, mem,
 +                        ((width + 15) & ~15), ((height + 15) & ~15),
 +                        SPLASH_DEPTH_16,
 +                        decdata);
 +      if (err)
 +              printk(KERN_INFO "bootsplash: "
 +                     "error while decompressing picture: %s (%d)\n",
 +                     jpg_errors[err - 1], err);
 +      vfree(decdata);
 +      vfree(mem);
 +      return err ? -1 : 0;
 +}
 +
 +static void splash_free(struct vc_data *vc, struct fb_info *info)
 +{
 +      struct splash_data *sd;
 +      struct splash_data *next;
 +      SPLASH_DEBUG();
 +      for (sd = vc->vc_splash_data; sd; sd = next) {
 +              next = sd->next;
 +              sd->pic->ref_cnt--;
 +              if (!sd->pic->ref_cnt) {
 +                      vfree(sd->pic->splash_pic);
 +                      vfree(sd->pic);
 +              }
 +              sd->imgd->ref_cnt--;
 +              if (!sd->imgd->ref_cnt) {
 +                      vfree(sd->imgd->splash_sboxes);
 +                      vfree(sd->imgd);
 +              }
 +              vfree(sd);
 +      }
 +      vc->vc_splash_data = 0;
 +      if (info)
 +              info->splash_data = 0;
 +}
 +
 +static int splash_mkpenguin(struct splash_data *data,
 +                          int pxo, int pyo, int pwi, int phe,
 +                          int pr, int pg, int pb)
 +{
 +      unsigned char *buf;
 +      int i;
 +
 +      if (pwi == 0 || phe == 0)
 +              return 0;
 +
 +      buf = (unsigned char *)data + sizeof(*data);
 +
 +      pwi += pxo - 1;
 +      phe += pyo - 1;
 +
 +      *buf++ = pxo;
 +      *buf++ = pxo >> 8;
 +      *buf++ = pyo;
 +      *buf++ = pyo >> 8;
 +      *buf++ = pwi;
 +      *buf++ = pwi >> 8;
 +      *buf++ = phe;
 +      *buf++ = phe >> 8;
 +      *buf++ = pr;
 +      *buf++ = pg;
 +      *buf++ = pb;
 +      *buf++ = 0;
 +
 +      for (i = 0; i < 12; i++, buf++)
 +              *buf = buf[-12];
 +
 +      buf[-24] ^= 0xff;
 +      buf[-23] ^= 0xff;
 +      buf[-1] = 0xff;
 +
 +      return 2;
 +}
 +
 +static const int splash_offsets[3][16] = {
 +    /* len, unit, size, state, fgcol, col, xo, yo, wi, he
 +       boxcnt, ssize, sboxcnt, percent, overok, palcnt */
 +    /* V1 */
 +      {   20,   -1,   16,    -1,    -1,  -1,  8, 10, 12, 14,
 +          -1,    -1,      -1,      -1,     -1,     -1 },
 +      /* V2 */
 +      {   35,    8,   12,     9,    10,  11, 16, 18, 20, 22,
 +          -1,    -1,      -1,      -1,     -1,     -1 },
 +      /* V3 */
 +      {   38,    8,   12,     9,    10,  11, 16, 18, 20, 22,
 +          24,    28,      32,      34,     36,     37 },
 +};
 +
 +#define SPLASH_OFF_LEN     offsets[0]
 +#define SPLASH_OFF_UNIT    offsets[1]
 +#define SPLASH_OFF_SIZE    offsets[2]
 +#define SPLASH_OFF_STATE   offsets[3]
 +#define SPLASH_OFF_FGCOL   offsets[4]
 +#define SPLASH_OFF_COL     offsets[5]
 +#define SPLASH_OFF_XO      offsets[6]
 +#define SPLASH_OFF_YO      offsets[7]
 +#define SPLASH_OFF_WI      offsets[8]
 +#define SPLASH_OFF_HE      offsets[9]
 +#define SPLASH_OFF_BOXCNT  offsets[10]
 +#define SPLASH_OFF_SSIZE   offsets[11]
 +#define SPLASH_OFF_SBOXCNT offsets[12]
 +#define SPLASH_OFF_PERCENT offsets[13]
 +#define SPLASH_OFF_OVEROK  offsets[14]
 +#define SPLASH_OFF_PALCNT  offsets[15]
 +
 +static inline int splash_getb(unsigned char *pos, int off)
 +{
 +      return off == -1 ? 0 : pos[off];
 +}
 +
 +static inline int splash_gets(unsigned char *pos, int off)
 +{
 +      return off == -1 ? 0 : pos[off] | pos[off + 1] << 8;
 +}
 +
 +static inline int splash_geti(unsigned char *pos, int off)
 +{
 +      return off == -1 ? 0 : (pos[off] |
 +                              pos[off + 1] << 8 |
 +                              pos[off + 2] << 16 |
 +                              pos[off + 3] << 24);
 +}
 +
 +/* move the given splash_data to the current one */
 +static void splash_pivot_current(struct vc_data *vc, struct splash_data *new)
 +{
 +      struct splash_data *sd;
 +      struct splash_pic_data *pic;
 +      int state, percent, silent;
 +
 +      sd = vc->vc_splash_data;
 +      if (!sd || sd == new)
 +              return;
 +
 +      state = sd->splash_state;
 +      percent = sd->splash_percent;
 +      silent = sd->splash_dosilent;
 +      if (sd->pic->ref_cnt > 1) {
 +              pic = kzalloc(sizeof(struct splash_pic_data), GFP_KERNEL);
 +              if (!pic)
 +                      return;
 +              sd->pic = pic;
 +      }
 +      sd->pic->ref_cnt = 1;
 +      sd->pic->splash_pic_size = 0;
 +      sd->pic->splash_pic = NULL;
 +      sd->splash_vc_text_wi = sd->imgd->splash_text_wi;
 +      sd->splash_vc_text_he = sd->imgd->splash_text_he;
 +      for (; sd->next; sd = sd->next) {
 +              if (sd->next == new) {
 +                      sd->next = new->next;
 +                      new->next = vc->vc_splash_data;
 +                      vc->vc_splash_data = new;
 +                      /* copy the current states */
 +                      new->splash_state = state;
 +                      new->splash_percent = percent;
 +                      new->splash_dosilent = silent;
 +                      new->splash_vc_text_wi = new->imgd->splash_text_wi;
 +                      new->splash_vc_text_he = new->imgd->splash_text_he;
 +
 +                      new->splash_boxes_xoff = 0;
 +                      new->splash_boxes_yoff = 0;
 +                      new->splash_sboxes_xoff = 0;
 +                      new->splash_sboxes_yoff = 0;
 +
 +                      if (new->pic->ref_cnt > 1) {
 +                              struct splash_pic_data *pic;
 +                              pic = kzalloc(sizeof(struct splash_pic_data),
 +                                            GFP_KERNEL);
 +                              if (!pic)
 +                                      return;
 +
 +                              new->pic = pic;
 +                      }
 +                      new->pic->ref_cnt = 1;
 +                      new->pic->splash_pic_size = 0;
 +                      new->pic->splash_pic = NULL;
 +
 +                      return;
 +              }
 +      }
 +}
 +
 +static int update_boxes(struct vc_data *vc,
 +             const int *offsets,
 +             unsigned char *ndata, int len, unsigned char * end,
 +             int *update)
 +{
 +      int boxcnt;
 +      int sboxcnt;
 +      struct splash_data *sd;
 +      struct splash_img_data *imgd;
 +      int i;
 +
 +      sd = vc->vc_splash_data;
 +      if (sd != 0) {
 +              int up = 0;
 +              imgd = sd->imgd;
 +              i = splash_getb(ndata, SPLASH_OFF_STATE);
 +              if (i != 255) {
 +                      sd->splash_state = i; /*@!@*/
 +                      up = -1;
 +              }
 +              i = splash_getb(ndata, SPLASH_OFF_FGCOL);
 +              if (i != 255) {
 +                      imgd->splash_fg_color = i;
 +                      up = -1;
 +              }
 +              i = splash_getb(ndata, SPLASH_OFF_COL);
 +              if (i != 255) {
 +                      imgd->splash_color = i;
 +                      up = -1;
 +              }
 +              boxcnt = sboxcnt = 0;
 +              if (ndata + len <= end) {
 +                      boxcnt = splash_gets(ndata, SPLASH_OFF_BOXCNT);
 +                      sboxcnt = splash_gets(ndata, SPLASH_OFF_SBOXCNT);
 +              }
 +              if (boxcnt) {
 +                      i = splash_gets(ndata, len);
 +                      if (boxcnt + i
 +                          <= imgd->splash_boxcount &&
 +                          ndata + len + 2 + boxcnt * 12
 +                          <= end) {
 +                              if (splash_geti(ndata, len + 2)
 +                                  != 0x7ffd7fff ||
 +                                  !memcmp(ndata + len + 2,
 +                                          imgd->splash_boxes + i * 12,
 +                                          8)) {
 +                                      memcpy(imgd->splash_boxes + i * 12,
 +                                             ndata + len + 2,
 +                                             boxcnt * 12);
 +                                      up |= 1;
 +                              }
 +                      }
 +                      len += boxcnt * 12 + 2;
 +              }
 +              if (sboxcnt) {
 +                      i = splash_gets(ndata, len);
 +                      if ((sboxcnt + i <= imgd->splash_sboxcount) &&
 +                          (ndata + len + 2 + sboxcnt * 12 <= end)) {
 +                              if ((splash_geti(ndata, len + 2) != 0x7ffd7fff)
 +                                  || !memcmp(ndata + len + 2,
 +                                             imgd->splash_sboxes + i * 12,
 +                                             8)) {
 +                                      memcpy(imgd->splash_sboxes + i * 12,
 +                                             ndata + len + 2,
 +                                             sboxcnt * 12);
 +                                      up |= 2;
 +                              }
 +                      }
 +              }
 +              if (update)
 +                      *update = up;
 +      }
 +      return 0;
 +}
 +
 +static int splash_getraw(unsigned char *start, unsigned char *end, int *update)
 +{
 +      unsigned char *ndata;
 +      int version;
 +      int splash_size;
 +      int unit;
 +      int width, height;
 +      int silentsize;
 +      int boxcnt;
 +      int sboxcnt;
 +      int palcnt;
 +      int len;
 +      const int *offsets;
 +      struct vc_data *vc = NULL;
 +      struct fb_info *info = NULL;
 +      struct splash_data *sd;
 +      struct splash_img_data *imgd;
 +      struct splash_pic_data *pic;
 +      struct splash_data *splash_found = NULL;
 +      int unit_found = -1;
 +      int oldpercent, oldsilent;
 +
 +      if (update)
 +              *update = -1;
 +
 +      if (!update ||
 +          start[7] < '2' ||
 +          start[7] > '3' ||
 +          splash_geti(start, 12) != (int)0xffffffff)
 +              printk(KERN_INFO "bootsplash %s: looking for picture...\n",
 +                     SPLASH_VERSION);
 +
 +      oldpercent = -3;
 +      oldsilent = -1;
 +      for (ndata = start; ndata < end; ndata++) {
 +              if (ndata[0] != 'B' ||
 +                  ndata[1] != 'O' ||
 +                  ndata[2] != 'O' ||
 +                  ndata[3] != 'T')
 +                      continue;
 +              if (ndata[4] != 'S' ||
 +                  ndata[5] != 'P' ||
 +                  ndata[6] != 'L' ||
 +                  ndata[7]  < '1' ||
 +                  ndata[7]  > '3')
 +                      continue;
 +
 +              version = ndata[7] - '0';
 +              offsets = splash_offsets[version - 1];
 +              len = SPLASH_OFF_LEN;
 +
 +              unit = splash_getb(ndata, SPLASH_OFF_UNIT);
 +              if (unit >= MAX_NR_CONSOLES)
 +                      continue;
 +
 +              if (unit)
 +                      vc_allocate(unit);
 +
 +              vc = vc_cons[unit].d;
 +              if (!vc)
 +                      continue;
 +
 +              info = registered_fb[(int)con2fb_map[unit]];
 +
 +              splash_size = splash_geti(ndata, SPLASH_OFF_SIZE);
 +
 +              /*
 +               * Update. Wonder what should happen here now
 +               * since we can have multiple splash_data records
 +               */
 +              if (splash_size == (int)0xffffffff && version > 1) {
 +                      if (update_boxes(vc, offsets, ndata, len, end, update) < 0)
 +                              return -1;
 +
 +                      return unit;
 +              }
 +
 +              if (splash_size == 0) {
 +                      printk(KERN_INFO
 +                             "bootsplash: ...found, freeing memory.\n");
 +                      if (vc->vc_splash_data)
 +                              splash_free(vc, info);
 +                      return unit;
 +              }
 +              boxcnt = splash_gets(ndata, SPLASH_OFF_BOXCNT);
 +              palcnt = 3 * splash_getb(ndata, SPLASH_OFF_PALCNT);
 +              if (ndata + len + splash_size > end) {
 +                      printk(KERN_ERR
 +                             "bootsplash: ...found, but truncated!\n");
 +                      return -1;
 +              }
 +              silentsize = splash_geti(ndata, SPLASH_OFF_SSIZE);
 +              if (silentsize)
 +                      printk(KERN_INFO
 +                             "bootsplash: silentjpeg size %d bytes\n",
 +                             silentsize);
 +              if (silentsize >= splash_size) {
 +                      printk(KERN_ERR "bootsplash: bigger than splashsize!\n");
 +                      return -1;
 +              }
 +              splash_size -= silentsize;
 +              if (!splash_usesilent)
 +                      silentsize = 0;
 +
 +              sboxcnt = splash_gets(ndata, SPLASH_OFF_SBOXCNT);
 +              if (vc->vc_splash_data) {
 +                      oldpercent = vc->vc_splash_data->splash_percent;/*@!@*/
 +                      oldsilent = vc->vc_splash_data->splash_dosilent;/*@!@*/
 +              }
 +              sd = kzalloc(sizeof(*sd), GFP_KERNEL);
 +              if (!sd)
 +                      break;
 +              imgd = vmalloc(sizeof(*imgd)
 +                             + splash_size + (version < 3 ? 2 * 12 : 0));
 +              if (!imgd) {
 +                      vfree(sd);
 +                      break;
 +              }
 +              pic = kzalloc(sizeof(*pic), GFP_KERNEL);
 +              if (!pic) {
 +                      vfree(sd);
 +                      vfree(pic);
 +                      break;
 +              }
 +              memset(imgd, 0, sizeof(*imgd));
 +              sd->imgd = imgd;
 +              sd->pic = pic;
 +              imgd->ref_cnt = 1;
 +              pic->ref_cnt = 1;
 +              jpeg_get_size(ndata + len + boxcnt * 12 + palcnt,
 +                            &imgd->splash_width, &imgd->splash_height);
 +              if (splash_check_jpeg(ndata + len + boxcnt * 12 + palcnt,
 +                                    imgd->splash_width,
 +                                    imgd->splash_height)) {
 +                      ndata += len + splash_size - 1;
 +                      vfree(imgd);
 +                      vfree(sd);
 +                      continue;
 +              }
 +              if (silentsize) {
 +                      imgd->splash_silentjpeg = vmalloc(silentsize);
 +                      if (imgd->splash_silentjpeg) {
 +                              memcpy(imgd->splash_silentjpeg,
 +                                     ndata + len + splash_size, silentsize);
 +                              imgd->splash_sboxes = imgd->splash_silentjpeg;
 +                              imgd->splash_silentjpeg += 12 * sboxcnt;
 +                              imgd->splash_sboxcount = sboxcnt;
 +                      }
 +              }
 +              imgd->splash_fg_color = splash_getb(ndata, SPLASH_OFF_FGCOL);
 +              imgd->splash_color = splash_getb(ndata, SPLASH_OFF_COL);
 +              imgd->splash_overpaintok = splash_getb(ndata, SPLASH_OFF_OVEROK);
 +              imgd->splash_text_xo = splash_gets(ndata, SPLASH_OFF_XO);
 +              imgd->splash_text_yo = splash_gets(ndata, SPLASH_OFF_YO);
 +              imgd->splash_text_wi = splash_gets(ndata, SPLASH_OFF_WI);
 +              imgd->splash_text_he = splash_gets(ndata, SPLASH_OFF_HE);
 +              if (version == 1) {
 +                      imgd->splash_text_xo *= 8;
 +                      imgd->splash_text_wi *= 8;
 +                      imgd->splash_text_yo *= 16;
 +                      imgd->splash_text_he *= 16;
 +                      imgd->splash_color    = (splash_default >> 8) & 0x0f;
 +                      imgd->splash_fg_color = (splash_default >> 4) & 0x0f;
 +              }
 +
 +              /* fake penguin box for older formats */
 +              if (version == 1)
 +                      boxcnt = splash_mkpenguin(sd, imgd->splash_text_xo + 10,
 +                                                imgd->splash_text_yo + 10,
 +                                                imgd->splash_text_wi - 20,
 +                                                imgd->splash_text_he - 20,
 +                                                0xf0, 0xf0, 0xf0);
 +              else if (version == 2)
 +                      boxcnt = splash_mkpenguin(sd,
 +                                                splash_gets(ndata, 24),
 +                                                splash_gets(ndata, 26),
 +                                                splash_gets(ndata, 28),
 +                                                splash_gets(ndata, 30),
 +                                                splash_getb(ndata, 32),
 +                                                splash_getb(ndata, 33),
 +                                                splash_getb(ndata, 34));
 +
 +              memcpy((char *)imgd
 +                     + sizeof(*imgd) + (version < 3 ? boxcnt * 12 : 0),
 +                     ndata + len,
 +                     splash_size);
 +              imgd->splash_boxcount = boxcnt;
 +              imgd->splash_boxes = (unsigned char *)imgd + sizeof(*imgd);
 +              imgd->splash_palette = imgd->splash_boxes + boxcnt * 12;
 +              imgd->splash_jpeg = imgd->splash_palette + palcnt;
 +
 +              sd->splash_state = splash_getb(ndata, SPLASH_OFF_STATE);/*@!@*/
 +              sd->splash_percent = oldpercent == -3 ?
 +                      splash_gets(ndata, SPLASH_OFF_PERCENT) :
 +                      oldpercent; /*@!@*/
 +              sd->pic->splash_pic = NULL;
 +              sd->pic->splash_pic_size = 0;
 +
 +              sd->splash_dosilent = imgd->splash_silentjpeg != 0 ?
 +                      (oldsilent == -1 ? 1 : oldsilent) :
 +                      0; /* @!@ */
 +
 +              sd->splash_vc_text_wi = imgd->splash_text_wi;
 +              sd->splash_vc_text_he = imgd->splash_text_he;
 +
 +              sd->next = vc->vc_splash_data;
 +              vc->vc_splash_data = sd;
 +
 +              if (info) {
 +                      width = info->var.xres;
 +                      height = info->var.yres;
 +                      if (imgd->splash_width != width ||
 +                          imgd->splash_height != height) {
 +                              ndata += len + splash_size - 1;
 +                              continue;
 +                      }
 +              }
 +              printk(KERN_INFO
 +                     "bootsplash: ...found (%dx%d, %d bytes, v%d).\n",
 +                     imgd->splash_width, imgd->splash_height,
 +                     splash_size, version);
 +              if (version == 1) {
 +                      printk(KERN_WARNING
 +                             "bootsplash: Using deprecated v1 header. "
 +                             "Updating your splash utility recommended.\n");
 +                      printk(KERN_INFO
 +                             "bootsplash: Find the latest version at "
 +                     "http://www.bootsplash.org/\n");
 +              }
 +
 +              splash_found = sd;
 +              unit_found = unit;
 +      }
 +
 +      if (splash_found) {
 +              splash_pivot_current(vc, splash_found);
 +              return unit_found;
 +      } else {
 +              vc = vc_cons[0].d;
 +              if (vc) {
 +                      info = registered_fb[(int)con2fb_map[0]];
 +                      if (info) {
 +                              width = info->var.xres;
 +                              height = info->var.yres;
 +                      } else
 +                              width = height = 0;
 +                      if (!splash_look_for_jpeg(vc, width, height))
 +                              return -1;
 +                      return 0;
 +              }
 +      }
 +
 +      printk(KERN_ERR "bootsplash: ...no good signature found.\n");
 +      return -1;
 +}
 +
 +static void splash_update_redraw(struct vc_data *vc, struct fb_info *info)
 +{
 +      update_region(vc,
 +                    vc->vc_origin + vc->vc_size_row * vc->vc_top,
 +                    vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
 +      splash_clear_margins(vc, info, 0);
 +}
 +
 +int splash_do_verbose(void)
 +{
 +      struct vc_data *vc;
 +      struct fb_info *info;
 +      int ret = 0;
 +
 +      SPLASH_DEBUG();
 +      if (!oops_in_progress)
 +              console_lock();
 +
 +      if (!splash_usesilent)
 +              goto done;
 +
 +      vc = vc_cons[0].d;
 +
 +      if (!vc || !vc->vc_splash_data || !vc->vc_splash_data->splash_state)
 +              goto done;
 +      if (!vc->vc_splash_data->imgd->splash_silentjpeg)
 +              goto done;
 +
 +      if (!vc->vc_splash_data->splash_dosilent)
 +              goto done;
 +      vc->vc_splash_data->splash_dosilent = 0;
 +      if (fg_console != vc->vc_num)
 +              goto done;
 +
 +      info = registered_fb[(int)con2fb_map[0]];
 +
 +      if (!info || !info->splash_data)
 +              goto done;
 +
 +      splash_update_redraw(vc, info);
 +      ret = 0;
 +
 + done:
 +      if (!oops_in_progress)
 +              console_unlock();
 +
 +      return ret;
 +}
 +
 +static void splash_verbose_callback(struct work_struct *ignored)
 +{
 +      splash_do_verbose();
 +}
 +
 +static DECLARE_WORK(splash_work, splash_verbose_callback);
 +
 +int splash_verbose(void)
 +{
 +      if (!oops_in_progress)
 +              schedule_work(&splash_work);
 +      else
 +              return splash_do_verbose();
 +      return 0;
 +}
 +
 +static void splash_off(struct vc_data *vc, struct fb_info *info)
 +{
 +      int rows = info->var.xres / vc->vc_font.width;
 +      int cols = info->var.yres / vc->vc_font.height;
 +      SPLASH_DEBUG();
 +
 +      info->splash_data = 0;
 +      if (rows != vc->vc_rows || cols != vc->vc_cols)
 +              vc_resize(vc, rows, cols);
 +}
 +
 +/* look for the splash with the matching size and set it as the current */
 +static int splash_look_for_jpeg(struct vc_data *vc, int width, int height)
 +{
 +      struct splash_data *sd, *found = NULL;
 +      int found_delta_x = INT_MAX, found_delta_y = INT_MAX;
 +
 +      for (sd = vc->vc_splash_data; sd; sd = sd->next) {
 +              int delta_x = abs(sd->imgd->splash_width - width) * height;
 +              int delta_y = abs(sd->imgd->splash_height - height) * width;
 +              if (!found ||
 +                  (found_delta_x + found_delta_y > delta_x + delta_y)) {
 +                      found = sd;
 +                      found_delta_x = delta_x;
 +                      found_delta_y = delta_y;
 +              }
 +      }
 +
 +      if (found) {
 +              SPLASH_DEBUG("bootsplash: "
 +                           "scalable image found (%dx%d scaled to %dx%d).",
 +                           found->imgd->splash_width,
 +                           found->imgd->splash_height,
 +                           width, height);
 +
 +              splash_pivot_current(vc, found);
 +
 +              /* textarea margins are constant independent from image size */
 +              if (found->imgd->splash_height != height)
 +                      found->splash_vc_text_he = height
 +                              - (found->imgd->splash_height
 +                                 - found->imgd->splash_text_he);
 +              else
 +                      found->splash_vc_text_he = found->imgd->splash_text_he;
 +              if (found->imgd->splash_width != width)
 +                      found->splash_vc_text_wi =
 +                              width
 +                              - (found->imgd->splash_width
 +                                 - found->imgd->splash_text_wi);
 +              else
 +                      found->splash_vc_text_wi = found->imgd->splash_text_wi;
 +
 +              if (found->imgd->splash_width != width
 +                  || found->imgd->splash_height != height) {
 +                      box_offsets(found->imgd->splash_boxes,
 +                                  found->imgd->splash_boxcount,
 +                                  width, height,
 +                                  found->imgd->splash_width,
 +                                  found->imgd->splash_height,
 +                                  &found->splash_boxes_xoff,
 +                                  &found->splash_boxes_yoff);
 +                      SPLASH_DEBUG("bootsplash: offsets for boxes: x=%d y=%d",
 +                                   found->splash_boxes_xoff,
 +                                   found->splash_boxes_yoff);
 +
 +                      if (found->imgd->splash_sboxes) {
 +                              box_offsets(found->imgd->splash_sboxes,
 +                                          found->imgd->splash_sboxcount,
 +                                          width, height,
 +                                          found->imgd->splash_width,
 +                                          found->imgd->splash_height,
 +                                          &found->splash_sboxes_xoff,
 +                                          &found->splash_sboxes_yoff);
 +                              SPLASH_DEBUG("bootsplash: "
 +                                           "offsets sboxes: x=%d y=%d",
 +                                           found->splash_sboxes_xoff,
 +                                           found->splash_sboxes_yoff);
 +                      }
 +              } else {
 +                      found->splash_sboxes_xoff = 0;
 +                      found->splash_sboxes_yoff = 0;
 +              }
 +              return 0;
 +      }
 +      return -1;
 +}
 +
 +static int splash_recolor(struct vc_data *vc, struct fb_info *info)
 +{
 +      int color;
 +
 +      SPLASH_DEBUG();
 +      if (!vc->vc_splash_data)
 +              return -1;
 +      if (!vc->vc_splash_data->splash_state)
 +              return 0;
 +      color = vc->vc_splash_data->imgd->splash_color << 4 |
 +              vc->vc_splash_data->imgd->splash_fg_color;
 +      if (vc->vc_def_color != color)
 +              con_remap_def_color(vc, color);
 +      if (info && info->splash_data && fg_console == vc->vc_num)
 +              splash_update_redraw(vc, info);
 +      vc->vc_splash_data->color_set = 1;
 +      return 0;
 +}
 +
 +int splash_prepare(struct vc_data *vc, struct fb_info *info)
 +{
 +      int err;
 +      int width, height, octpp, size, sbytes;
 +      enum splash_color_format cf = SPLASH_DEPTH_UNKNOWN;
 +      int pic_update = 0;
 +      struct jpeg_decdata *decdata; /* private decoder data */
 +
 +      SPLASH_DEBUG("vc_num: %i", vc->vc_num);
 +
 +#if 0 /* Nouveau fb sets a different ops, so we can't use the condition */
 +      if (info->fbops->fb_imageblit != cfb_imageblit) {
 +              printk(KERN_ERR "bootsplash: "
 +                     "found, but framebuffer can't "
 +                     "handle it!\n");
 +              return -1;
 +      }
 +#endif
 +
 +      if (!vc->vc_splash_data || !vc->vc_splash_data->splash_state) {
 +              splash_off(vc, info);
 +              return -1;
 +      }
 +
 +      width = info->var.xres;
 +      height = info->var.yres;
 +      switch (info->var.bits_per_pixel) {
 +      case 16:
 +              if ((info->var.red.length +
 +                   info->var.green.length +
 +                   info->var.blue.length) == 15)
 +                      cf = SPLASH_DEPTH_15;
 +              else
 +                      cf = SPLASH_DEPTH_16;
 +              break;
 +      case 24:
 +              cf = SPLASH_DEPTH_24_PACKED;
 +              break;
 +      case 32:
 +              cf = SPLASH_DEPTH_24;
 +              break;
 +      }
 +      if (cf == SPLASH_DEPTH_UNKNOWN) {
 +              printk(KERN_INFO "bootsplash: unsupported pixel format: %i\n",
 +                     info->var.bits_per_pixel);
 +              splash_off(vc, info);
 +              return -2;
 +      }
 +      octpp = splash_octpp(cf);
 +
 +      if (splash_look_for_jpeg(vc, width, height) < 0) {
 +              printk(KERN_INFO "bootsplash: no matching splash %dx%d\n",
 +                     width, height);
 +              splash_off(vc, info);
 +              return -2;
 +      }
 +
 +      sbytes = ((width + 15) & ~15) * octpp;
 +      size = sbytes * ((height + 15) & ~15);
 +
 +      if (size != vc->vc_splash_data->pic->splash_pic_size) {
 +              if (vc->vc_splash_data->pic->ref_cnt > 1) {
 +                      struct splash_pic_data *pic;
 +                      pic = kzalloc(sizeof(struct splash_pic_data),
 +                                    GFP_KERNEL);
 +                      if (!pic)
 +                              return -2;
 +                      vc->vc_splash_data->pic = pic;
 +              }
 +              vc->vc_splash_data->pic->ref_cnt = 1;
 +              vc->vc_splash_data->pic->splash_pic = NULL;
 +              vc->vc_splash_data->pic->splash_pic_size = 0;
 +      }
 +      if (!vc->vc_splash_data->pic->splash_pic) {
 +              vc->vc_splash_data->pic->splash_pic = vmalloc(size);
 +              pic_update = 1;
 +      }
 +      if (!vc->vc_splash_data->pic->splash_pic) {
 +              printk(KERN_INFO "bootsplash: not enough memory.\n");
 +              splash_off(vc, info);
 +              return -3;
 +      }
 +
 +      decdata = vmalloc(sizeof(*decdata));
 +      if (!decdata) {
 +              printk(KERN_INFO "bootsplash: not enough memory.\n");
 +              splash_off(vc, info);
 +              return -3;
 +      }
 +
 +      if (vc->vc_splash_data->imgd->splash_silentjpeg &&
 +          vc->vc_splash_data->splash_dosilent) {
 +              pic_update = 1;
 +              err = jpeg_get(vc->vc_splash_data->imgd->splash_silentjpeg,
 +                             vc->vc_splash_data->pic->splash_pic,
 +                             width, height, cf, decdata);
 +              if (err) {
 +                      printk(KERN_INFO "bootsplash: "
 +                             "error while decompressing silent picture: "
 +                             "%s (%d)\n",
 +                             jpg_errors[err - 1], err);
 +                      vc->vc_splash_data->splash_dosilent = 0;
 +              } else {
 +                      if (vc->vc_splash_data->imgd->splash_sboxcount)
 +                              boxit(vc->vc_splash_data->pic->splash_pic,
 +                                    sbytes,
 +                                    vc->vc_splash_data->imgd->splash_sboxes,
 +                                    vc->vc_splash_data->imgd->splash_sboxcount,
 +                                    vc->vc_splash_data->splash_percent,
 +                                    vc->vc_splash_data->splash_sboxes_xoff,
 +                                    vc->vc_splash_data->splash_sboxes_yoff,
 +                                    vc->vc_splash_data->splash_percent < 0 ?
 +                                    1 : 0,
 +                                    cf);
 +                      splashcopy(info->screen_base,
 +                                 vc->vc_splash_data->pic->splash_pic,
 +                                 info->var.yres,
 +                                 info->var.xres,
 +                                 info->fix.line_length, sbytes,
 +                                 octpp);
 +              }
 +      } else
 +              vc->vc_splash_data->splash_dosilent = 0;
 +
 +      if (pic_update) {
 +              err = jpeg_get(vc->vc_splash_data->imgd->splash_jpeg,
 +                             vc->vc_splash_data->pic->splash_pic,
 +                             width, height, cf, decdata);
 +              if (err) {
 +                      printk(KERN_INFO "bootsplash: "
 +                             "error while decompressing picture: %s (%d) .\n",
 +                             jpg_errors[err - 1], err);
 +                      splash_off(vc, info);
 +                      return -4;
 +              }
 +      }
 +
 +      vfree(decdata);
 +
 +      vc->vc_splash_data->pic->splash_pic_size = size;
 +      vc->vc_splash_data->pic->splash_pic_stride = sbytes;
 +
 +      if (vc->vc_splash_data->imgd->splash_boxcount)
 +              boxit(vc->vc_splash_data->pic->splash_pic,
 +                    sbytes,
 +                    vc->vc_splash_data->imgd->splash_boxes,
 +                    vc->vc_splash_data->imgd->splash_boxcount,
 +                    vc->vc_splash_data->splash_percent,
 +                    vc->vc_splash_data->splash_boxes_xoff,
 +                    vc->vc_splash_data->splash_boxes_yoff,
 +                    0,
 +                    cf);
 +      if (vc->vc_splash_data->splash_state) {
 +              int cols = vc->vc_splash_data->splash_vc_text_wi
 +                      / vc->vc_font.width;
 +              int rows = vc->vc_splash_data->splash_vc_text_he
 +                      / vc->vc_font.height;
 +
 +              info->splash_data = vc->vc_splash_data;
 +
 +              info->splash_data->need_sync = 0;
 +              /* XEN fb needs some sync after the direct modification of
 +               * fb area; maybe other FBs would need similar hack, but
 +               * so far I don't care.
 +               */
 +              if (!strcmp(info->fix.id, "xen")) {
 +                      info->splash_data->need_sync = 1;
 +                      /* sync the whole splash once */
 +                      splash_sync_region(info, 0, 0,
 +                                         info->var.xres, info->var.yres);
 +              }
 +
 +              /* vc_resize also calls con_switch which resets yscroll */
 +              if (rows != vc->vc_rows || cols != vc->vc_cols)
 +                      vc_resize(vc, cols, rows);
 +              if (!vc->vc_splash_data->color_set)
 +                      splash_recolor(vc, NULL);
 +      } else {
 +              SPLASH_DEBUG("Splash Status is off\n");
 +              splash_off(vc, info);
 +              return -5;
 +      }
 +      return 0;
 +}
 +
 +
 +#ifdef CONFIG_PROC_FS
 +
 +#include <linux/proc_fs.h>
 +
 +static int splash_read_proc(char *buffer, char **start, off_t offset, int size,
 +                          int *eof, void *data);
 +static int splash_write_proc(struct file *file, const char *buffer,
 +                           unsigned long count, void *data);
 +static int splash_status(struct vc_data *vc);
 +static int splash_proc_register(void);
 +
 +static struct proc_dir_entry *proc_splash;
 +
 +static int splash_status(struct vc_data *vc)
 +{
 +      struct fb_info *info;
 +
 +      printk(KERN_INFO "bootsplash: status on console %d changed to %s\n",
 +             vc->vc_num,
 +             vc->vc_splash_data &&
 +             vc->vc_splash_data->splash_state ? "on" : "off");
 +
 +      info = registered_fb[(int) con2fb_map[vc->vc_num]];
 +      if (!info)
 +              return 0;
 +
 +      if (fg_console == vc->vc_num)
 +              splash_prepare(vc, info);
 +      if (vc->vc_splash_data && vc->vc_splash_data->splash_state)
 +              splash_recolor(vc, info);
 +      else {
 +              splash_off(vc, info);
 +              if (vc->vc_def_color != 0x07)
 +                      con_remap_def_color(vc, 0x07);
 +      }
 +
 +      return 0;
 +}
 +
 +int splash_copy_current_img(int unit_s, int unit_t)
 +{
 +      struct fb_info *info;
 +      struct vc_data *vc_s;
 +      struct vc_data *vc_t;
 +      struct splash_data *sd_s;
 +      struct splash_data *sd_t;
 +      int size;
 +
 +      if (unit_s >= MAX_NR_CONSOLES || unit_t >= MAX_NR_CONSOLES)
 +              return -1;
 +
 +      vc_s = vc_cons[unit_s].d;
 +      if (!vc_s) {
 +              printk(KERN_WARNING "bootsplash: "
 +                     "copy: source (%i) is invalid.\n", unit_s);
 +              return -1;
 +      }
 +      sd_s = vc_s->vc_splash_data;
 +      if (!sd_s || !sd_s->imgd) {
 +              printk(KERN_INFO "bootsplash: "
 +                     "copy: source_vc (%i) doesn't have valid splash data.\n",
 +                     unit_s);
 +              return -1;
 +      }
 +      vc_allocate(unit_t);
 +      vc_t = vc_cons[unit_t].d;
 +      if (!vc_t) {
 +              printk(KERN_WARNING "bootsplash: copy: dest (%i) is invalid.\n",
 +                     unit_t);
 +              return -1;
 +      }
 +      sd_t = kzalloc(sizeof(*sd_t), GFP_KERNEL);
 +      if (!sd_t)
 +              return -1;
 +      vc_t->vc_splash_data = sd_t;
 +
 +      sd_t->imgd = sd_s->imgd;
 +      sd_t->imgd->ref_cnt++;
 +
 +      /* now recreate all the rest */
 +      sd_t->splash_state = sd_s->splash_state;
 +      sd_t->splash_percent = sd_s->splash_percent;
 +      sd_t->splash_dosilent = sd_s->splash_dosilent;
 +      sd_t->splash_vc_text_wi = sd_s->imgd->splash_text_wi;
 +      sd_t->splash_vc_text_he = sd_s->imgd->splash_text_he;
 +
 +      sd_t->splash_boxes_xoff = 0;
 +      sd_t->splash_boxes_yoff = 0;
 +      sd_t->splash_sboxes_xoff = 0;
 +      sd_t->splash_sboxes_yoff = 0;
 +
 +      info = registered_fb[(int) con2fb_map[vc_t->vc_num]];
 +      size = (((info->var.xres + 15) & ~15)
 +              * ((info->var.bits_per_pixel + 1) >> 3))
 +              * ((info->var.yres + 15) & ~15);
 +      if (size != vc_s->vc_splash_data->pic->splash_pic_size) {
 +              sd_t->pic = kzalloc(sizeof(struct splash_pic_data), GFP_KERNEL);
 +              if (!sd_t->pic)
 +                      return -1;
 +              sd_t->pic->ref_cnt = 1;
 +      } else {
 +              sd_t->pic = sd_s->pic;
 +              sd_t->pic->ref_cnt++;
 +      }
 +
 +      splash_status(vc_t);
 +
 +      return 0;
 +}
 +
 +static int splash_read_proc(char *buffer, char **start, off_t offset, int size,
 +                      int *eof, void *data)
 +{
 +      int len;
 +      int xres, yres;
 +      struct vc_data *vc = vc_cons[0].d;
 +      struct fb_info *info = registered_fb[(int)con2fb_map[0]];
 +      int color = vc->vc_splash_data ?
 +              vc->vc_splash_data->imgd->splash_color << 4 |
 +              vc->vc_splash_data->imgd->splash_fg_color : splash_default >> 4;
 +      int status = vc->vc_splash_data ?
 +              vc->vc_splash_data->splash_state & 1 : 0;
 +
 +      if (info) {
 +              xres = info->var.xres;
 +              yres = info->var.yres;
 +      } else
 +              xres = yres = 0;
 +
 +      len = sprintf(buffer, "Splash screen v%s (0x%02x, %dx%d%s): %s\n",
 +                    SPLASH_VERSION, color, xres, yres,
 +                    (vc->vc_splash_data ?
 +                     vc->vc_splash_data->splash_dosilent : 0) ? ", silent" :
 +                    "",
 +                    status ? "on" : "off");
 +      if (offset >= len)
 +              return 0;
 +
 +      *start = buffer - offset;
 +
 +      return (size < len - offset ? size : len - offset);
 +}
 +
 +void splash_set_percent(struct vc_data *vc, int pe)
 +{
 +      struct fb_info *info;
 +      struct fbcon_ops *ops;
 +      struct splash_data *vc_splash_data;
 +      int oldpe;
 +
 +      SPLASH_DEBUG(" console: %d val: %d\n", vc->vc_num, pe);
 +
 +      if (pe < -2)
 +              pe = 0;
 +      if (pe > 65535)
 +              pe = 65535;
 +      pe += pe > 32767;
 +
 +      vc_splash_data = vc->vc_splash_data;
 +      if (!vc_splash_data || vc_splash_data->splash_percent == pe)
 +              return;
 +
 +      oldpe = vc_splash_data->splash_percent;
 +      vc_splash_data->splash_percent = pe;
 +      if (fg_console != vc->vc_num ||
 +          !vc_splash_data->splash_state) {
 +              return;
 +      }
 +      info = registered_fb[(int) con2fb_map[vc->vc_num]];
 +      if (!info)
 +              return;
 +
 +      ops = info->fbcon_par;
 +      if (ops->blank_state)
 +              return;
 +      if (!vc_splash_data->imgd->splash_overpaintok
 +          || pe == 65536
 +          || pe < oldpe) {
 +              if (splash_hasinter(vc_splash_data->imgd->splash_boxes,
 +                                  vc_splash_data->imgd->splash_boxcount)) {
 +                      splash_status(vc);
 +              } else
 +                      splash_prepare(vc, info);
 +      } else {
 +              struct splash_data *splash_data = info->splash_data;
 +              enum splash_color_format cf = SPLASH_DEPTH_UNKNOWN;
 +              switch (info->var.bits_per_pixel) {
 +              case 16:
 +                      if ((info->var.red.length +
 +                           info->var.green.length +
 +                           info->var.blue.length) == 15)
 +                              cf = SPLASH_DEPTH_15;
 +                      else
 +                              cf = SPLASH_DEPTH_16;
 +                      break;
 +              case 24:
 +                      cf = SPLASH_DEPTH_24_PACKED;
 +                      break;
 +              case 32:
 +                      cf = SPLASH_DEPTH_24;
 +                      break;
 +              }
 +              if (cf == SPLASH_DEPTH_UNKNOWN)
 +                      return;
 +              if (splash_data) {
 +                      if (splash_data->imgd->splash_silentjpeg
 +                          && splash_data->splash_dosilent) {
 +                              boxit(info->screen_base,
 +                                    info->fix.line_length,
 +                                    splash_data->imgd->splash_sboxes,
 +                                    splash_data->imgd->splash_sboxcount,
 +                                    splash_data->splash_percent,
 +                                    splash_data->splash_sboxes_xoff,
 +                                    splash_data->splash_sboxes_yoff,
 +                                    1,
 +                                    cf);
 +                              /* FIXME: get a proper width/height */
 +                              splash_sync_region(info,
 +                                      splash_data->splash_sboxes_xoff,
 +                                      splash_data->splash_sboxes_yoff,
 +                                      info->var.xres -
 +                                      splash_data->splash_sboxes_xoff,
 +                                      8);
 +                      }
 +              }
 +      }
 +}
 +
 +static const char *get_unit(const char *buffer, int *unit)
 +{
 +
 +      *unit = -1;
 +      if (buffer[0] >= '0' && buffer[0] <= '9') {
 +              *unit = buffer[0] - '0';
 +              buffer++;
 +              if (buffer[0] >= '0' && buffer[0] <= '9') {
 +                      *unit = *unit * 10 + buffer[0] - '0';
 +                      buffer++;
 +              }
 +              if (*buffer == ' ')
 +                      buffer++;
 +      }
 +      return buffer;
 +}
 +
 +static int splash_write_proc(struct file *file, const char *buffer,
 +                           unsigned long count, void *data)
 +{
 +      int new, unit;
 +      unsigned long uval;
 +      struct vc_data *vc;
 +      struct splash_data *vc_splash_data;
 +
 +      SPLASH_DEBUG();
 +
 +      if (!buffer || !splash_default)
 +              return count;
 +
 +      console_lock();
 +      unit = 0;
 +      if (buffer[0] == '@') {
 +              buffer++;
 +              buffer = get_unit(buffer, &unit);
 +              if (unit < 0 || unit >= MAX_NR_CONSOLES || !vc_cons[unit].d) {
 +                      console_unlock();
 +                      return count;
 +              }
 +      }
 +      SPLASH_DEBUG(" unit: %i", unit);
 +      vc = vc_cons[unit].d;
 +      vc_splash_data = vc->vc_splash_data;
 +
 +      if (!strncmp(buffer, "redraw", 6)) {
 +              SPLASH_DEBUG(" redraw");
 +              splash_status(vc);
 +              console_unlock();
 +              return count;
 +      }
 +
 +      if (!strncmp(buffer, "show", 4) || !strncmp(buffer, "hide", 4)) {
 +              long int pe;
 +
 +              SPLASH_DEBUG("show/hide");
 +              if (buffer[4] == ' ' && buffer[5] == 'p')
 +                      pe = 0;
 +              else if (buffer[4] == '\n')
 +                      pe = 65535;
 +              else if (strict_strtol(buffer + 5, 0, &pe) == -EINVAL)
 +                      pe = 0;
 +              if (pe < -2)
 +                      pe = 0;
 +              if (pe > 65535)
 +                      pe = 65535;
 +              if (*buffer == 'h')
 +                      pe = 65535 - pe;
 +              splash_set_percent(vc, pe);
 +              console_unlock();
 +              return count;
 +      }
 +
 +      if (!strncmp(buffer, "copy", 4)) {
 +              buffer += 4;
 +              if (buffer[0] == ' ')
 +                      buffer++;
 +              buffer = get_unit(buffer, &unit);
 +              if (unit < 0 || unit >= MAX_NR_CONSOLES) {
 +                      console_unlock();
 +                      return count;
 +              }
 +              buffer = get_unit(buffer, &new);
 +              if (new < 0 || new >= MAX_NR_CONSOLES) {
 +                      console_unlock();
 +                      return count;
 +              }
 +              splash_copy_current_img(unit, new);
 +              console_unlock();
 +              return count;
 +      }
 +
 +      if (!strncmp(buffer, "silent\n", 7)
 +          || !strncmp(buffer, "verbose\n", 8)) {
 +              SPLASH_DEBUG(" silent/verbose");
 +
 +              if (vc_splash_data &&
 +                  vc_splash_data->imgd->splash_silentjpeg) {
 +                      if (vc_splash_data->splash_dosilent !=
 +                          (buffer[0] == 's')) {
 +                              vc_splash_data->splash_dosilent =
 +                                      buffer[0] == 's';
 +                              splash_status(vc);
 +                      }
 +              }
 +              console_unlock();
 +              return count;
 +      }
 +
 +      if (!strncmp(buffer, "freesilent\n", 11)) {
 +              SPLASH_DEBUG(" freesilent");
 +
 +              if (vc_splash_data &&
 +                  vc_splash_data->imgd->splash_silentjpeg) {
 +                      struct splash_data *sd;
 +                      printk(KERN_INFO "bootsplash: freeing silent jpeg\n");
 +                      for (sd = vc_splash_data; sd; sd = sd->next) {
 +                              sd->imgd->splash_silentjpeg = 0;
 +                              vfree(sd->imgd->splash_sboxes);
 +                              sd->imgd->splash_sboxes = 0;
 +                              sd->imgd->splash_sboxcount = 0;
 +                      }
 +                      if (vc_splash_data->splash_dosilent)
 +                              splash_status(vc);
 +
 +                      vc->vc_splash_data->splash_dosilent = 0;
 +              }
 +              console_unlock();
 +              return count;
 +      }
 +
 +      if (!strncmp(buffer, "BOOTSPL", 7)) {
 +              int up = -1;
 +
 +              SPLASH_DEBUG(" BOOTSPL");
 +              unit = splash_getraw((unsigned char *)buffer,
 +                                   (unsigned char *)buffer + count,
 +                                   &up);
 +              SPLASH_DEBUG(" unit: %i up: %i", unit, up);
 +              if (unit >= 0) {
 +                      struct fb_info *info;
 +
 +                      vc = vc_cons[unit].d;
 +                      info = registered_fb[(int) con2fb_map[vc->vc_num]];
 +                      if (!info) {
 +                              console_unlock();
 +                              return count;
 +                      }
 +
 +                      if (up == -1) {
 +                              splash_status(vc);
 +                      } else {
 +                              struct splash_data *vc_splash_data
 +                                      = vc->vc_splash_data;
 +                              struct splash_data *splash_data
 +                                      = info->splash_data;
 +                              struct fbcon_ops *ops = info->fbcon_par;
 +                              enum splash_color_format cf = SPLASH_DEPTH_UNKNOWN;
 +
 +                              switch (info->var.bits_per_pixel) {
 +                              case 16:
 +                                      if ((info->var.red.length +
 +                                           info->var.green.length +
 +                                           info->var.blue.length) == 15)
 +                                              cf = SPLASH_DEPTH_15;
 +                                      else
 +                                              cf = SPLASH_DEPTH_16;
 +                                      break;
 +                              case 24:
 +                                      cf = SPLASH_DEPTH_24_PACKED;
 +                                      break;
 +                              case 32:
 +                                      cf = SPLASH_DEPTH_24;
 +                                      break;
 +                              }
 +                              if (cf == SPLASH_DEPTH_UNKNOWN)
 +                                      up = 0;
 +                              if (ops->blank_state ||
 +                                  !vc_splash_data ||
 +                                  !splash_data)
 +                                      up = 0;
 +                              if ((up & 2) != 0
 +                                  && splash_data->imgd->splash_silentjpeg
 +                                  && splash_data->splash_dosilent) {
 +                                      boxit(info->screen_base,
 +                                            info->fix.line_length,
 +                                            splash_data->imgd->splash_sboxes,
 +                                            splash_data->imgd->splash_sboxcount,
 +                                            splash_data->splash_percent,
 +                                            splash_data->splash_sboxes_xoff,
 +                                            splash_data->splash_sboxes_yoff,
 +                                            1,
 +                                            cf);
 +                              } else if ((up & 1) != 0) {
 +                                      boxit(info->screen_base,
 +                                            info->fix.line_length,
 +                                            splash_data->imgd->splash_boxes,
 +                                            splash_data->imgd->splash_boxcount,
 +                                            splash_data->splash_percent,
 +                                            splash_data->splash_boxes_xoff,
 +                                            splash_data->splash_boxes_yoff,
 +                                            1,
 +                                            cf);
 +                              }
 +                      }
 +              }
 +              console_unlock();
 +              return count;
 +      }
 +
 +      if (!vc_splash_data) {
 +              console_unlock();
 +              return count;
 +      }
 +
 +      if (buffer[0] == 't') {
 +              vc_splash_data->splash_state ^= 1;
 +              SPLASH_DEBUG(" t");
 +              splash_status(vc);
 +              console_unlock();
 +              return count;
 +      }
 +      if (strict_strtoul(buffer, 0, &uval) == -EINVAL)
 +              uval = 1;
 +      if (uval > 1) {
 +              /* expert user */
 +              vc_splash_data->imgd->splash_color    = uval >> 8 & 0xff;
 +              vc_splash_data->imgd->splash_fg_color = uval >> 4 & 0x0f;
 +      }
 +      if ((uval & 1) == vc_splash_data->splash_state)
 +              splash_recolor(vc, NULL);
 +      else {
 +              vc_splash_data->splash_state = uval & 1;
 +              splash_status(vc);
 +      }
 +      console_unlock();
 +      return count;
 +}
 +
 +static int splash_proc_register(void)
 +{
 +      proc_splash = create_proc_entry("splash", 0, 0);
 +      if (proc_splash) {
 +              proc_splash->read_proc = splash_read_proc;
 +              proc_splash->write_proc = splash_write_proc;
 +              return 0;
 +      }
 +      return 1;
 +}
 +
 +#endif        /* CONFIG_PROC_FS */
 +
 +#define INIT_CONSOLE 0
 +
 +void splash_init(void)
 +{
 +      static bool splash_not_initialized = true;
 +      struct fb_info *info;
 +      struct vc_data *vc;
 +      int isramfs = 1;
 +      int fd;
 +      int len;
 +      int max_len = 1024*1024*2;
 +      char *mem;
 +
 +      if (splash_not_initialized == false)
 +              return;
 +      vc = vc_cons[INIT_CONSOLE].d;
 +      info = registered_fb[(int)con2fb_map[INIT_CONSOLE]];
 +      if (!vc
 +          || !info
 +          || info->var.bits_per_pixel < 16) /* not supported */
 +              return;
 +#ifdef CONFIG_PROC_FS
 +      splash_proc_register();
 +#endif
 +      splash_not_initialized = false;
 +      if (vc->vc_splash_data)
 +              return;
 +      fd = sys_open("/bootsplash", O_RDONLY, 0);
 +      if (fd < 0) {
 +              isramfs = 0;
 +              fd = sys_open("/initrd.image", O_RDONLY, 0);
 +      }
 +      if (fd < 0)
 +              return;
 +      len = (int)sys_lseek(fd, (off_t)0, 2);
 +      if (len <= 0) {
 +              sys_close(fd);
 +              return;
 +      }
 +      /* Don't look for more than the last 2MB */
 +      if (len > max_len) {
 +              printk(KERN_INFO "bootsplash: "
 +                     "scanning last %dMB of initrd for signature\n",
 +                     max_len>>20);
 +              sys_lseek(fd, (off_t)(len - max_len), 0);
 +              len = max_len;
 +      } else {
 +              sys_lseek(fd, (off_t)0, 0);
 +      }
 +
 +      mem = vmalloc(len);
 +      if (mem) {
 +              console_lock();
 +              if ((int)sys_read(fd, mem, len) == len
 +                  && (splash_getraw((unsigned char *)mem,
 +                                    (unsigned char *)mem + len, (int *)0)
 +                      == INIT_CONSOLE)
 +                  && vc->vc_splash_data)
 +                      vc->vc_splash_data->splash_state = splash_default & 1;
 +              console_unlock();
 +              vfree(mem);
 +      }
 +      sys_close(fd);
 +      if (isramfs)
 +              sys_unlink("/bootsplash");
 +      return;
 +}
 +
 +#define SPLASH_ALIGN 15
 +
 +static u32 *do_coefficients(u32 from, u32 to, u32 *shift)
 +{
 +      u32 *coefficients;
 +      u32 left = to;
 +      int n = 1;
 +      u32 upper = 31;
 +      int col_cnt = 0;
 +      int row_cnt = 0;
 +      int m;
 +      u32 rnd = from >> 1;
 +
 +      if (from > to) {
 +              left = to;
 +              rnd = from >> 1;
 +
 +              while (upper > 0) {
 +                      if ((1 << upper) & from)
 +                              break;
 +                      upper--;
 +              }
 +              upper++;
 +
 +              *shift = 32 - 8 - 1 - upper;
 +
 +              coefficients = vmalloc(sizeof(u32) * (from / to + 2) * from + 1);
 +              if (!coefficients)
 +                      return NULL;
 +
 +              n = 1;
 +              while (1) {
 +                      u32 sum = left;
 +                      col_cnt = 0;
 +                      m = n++;
 +                      while (sum < from) {
 +                              coefficients[n++] =
 +                                      ((left << *shift) + rnd) / from;
 +                              col_cnt++;
 +                              left = to;
 +                              sum += left;
 +                      }
 +                      left = sum - from;
 +                      coefficients[n++] =
 +                              (((to - left) << *shift) + rnd) / from;
 +                      col_cnt++;
 +                      coefficients[m] = col_cnt;
 +                      row_cnt++;
 +                      if (!left) {
 +                              coefficients[0] = row_cnt;
 +                              return coefficients;
 +                      }
 +              }
 +      } else {
 +              left = 0;
 +              rnd = to >> 1;
 +
 +              while (upper > 0) {
 +                      if ((1 << upper) & to)
 +                              break;
 +                      upper--;
 +              }
 +              upper++;
 +
 +              *shift = 32 - 8 - 1 - upper;
 +
 +              coefficients = vmalloc(sizeof(u32) * 3 * from + 1);
 +              if (!coefficients)
 +                      return NULL;
 +
 +              while (1) {
 +                      u32 diff;
 +                      u32 sum = left;
 +                      col_cnt = 0;
 +                      row_cnt++;
 +                      while (sum < to) {
 +                              col_cnt++;
 +                              sum += from;
 +                      }
 +                      left = sum - to;
 +                      diff = from - left;
 +                      if (!left) {
 +                              coefficients[n] = col_cnt;
 +                              coefficients[0] = row_cnt;
 +                              return coefficients;
 +                      }
 +                      coefficients[n++] = col_cnt - 1;
 +                      coefficients[n++] = ((diff << *shift) + rnd) / from;
 +                      coefficients[n++] = ((left << *shift) + rnd) / from;
 +              }
 +      }
 +}
 +
 +
 +struct pixel {
 +      u32 red;
 +      u32 green;
 +      u32 blue;
 +};
 +
 +#define put_pixel(pix, buf, cf)                                               \
 +      switch (cf) {                                                   \
 +      case SPLASH_DEPTH_15:                                           \
 +              *(u16 *)(buf) = (u16)((pix).red << 10 |                 \
 +                                    (pix).green << 5 | (pix).blue);   \
 +      (buf) += 2;                                                     \
 +      break;                                                          \
 +      case SPLASH_DEPTH_16:                                           \
 +              *(u16 *)(buf) = (u16)((pix).red << 11 |                 \
 +                                    (pix).green << 5 | (pix).blue);   \
 +              (buf) += 2;                                             \
 +              break;                                                  \
 +      case SPLASH_DEPTH_24_PACKED:                                    \
 +              *(u16 *)(buf) = (u16)((pix).red << 8 | (pix).green);    \
 +              buf += 2;                                               \
 +              *((buf)++) = (pix).blue;                                \
 +              break;                                                  \
 +      case SPLASH_DEPTH_24:                                           \
 +              *(u32 *)(buf) = (u32)((pix).red << 16 |                 \
 +                                    (pix).green << 8 | (pix).blue);   \
 +              (buf) += 4;                                             \
 +              break;                                                  \
 +        case SPLASH_DEPTH_UNKNOWN:                                    \
 +              break;                                                  \
 +      }
 +
 +#define get_pixel(pix, buf, depth)                                   \
 +      switch (depth) {                                               \
 +      case SPLASH_DEPTH_15:                                          \
 +              (pix).red = ((*(u16 *)(buf)) >> 10) & 0x1f;            \
 +              (pix).green = ((*(u16 *)(buf)) >> 5) & 0x1f;           \
 +              (pix).blue = (*(u16 *)(buf)) & 0x1f;                   \
 +              (buf) += 2;                                            \
 +              break;                                                 \
 +      case SPLASH_DEPTH_16:                                          \
 +              (pix).red = ((*(u16 *)(buf)) >> 11) & 0x1f;            \
 +              (pix).green = ((*(u16 *)(buf)) >> 5) & 0x3f;           \
 +              (pix).blue = (*(u16 *)(buf)) & 0x1f;                   \
 +              (buf) += 2;                                            \
 +              break;                                                 \
 +      case SPLASH_DEPTH_24_PACKED:                                   \
 +              (pix).blue = *(((buf))++);                             \
 +              (pix).green = *(((buf))++);                            \
 +              (pix).red = *(((buf))++);                              \
 +              break;                                                 \
 +      case SPLASH_DEPTH_24:                                          \
 +              (pix).blue = *(((buf))++);                             \
 +              (pix).green = *(((buf))++);                            \
 +              (pix).red = *(((buf))++);                              \
 +              (buf)++;                                               \
 +              break;                                                 \
 +       case SPLASH_DEPTH_UNKNOWN:                                    \
 +              break;                                                 \
 +      }
 +
 +static inline void
 +scale_x_down(enum splash_color_format cf, int src_w,
 +           unsigned char **src_p, u32 *x_coeff,
 +           u32 x_shift,  u32 y_coeff, struct pixel *row_buffer)
 +{
 +      u32 curr_x_coeff = 1;
 +      struct pixel curr_pixel, tmp_pixel;
 +      u32 x_array_size = x_coeff[0];
 +      int x_column_num;
 +      int i;
 +      int l, m;
 +      int k = 0;
 +      u32 rnd = (1 << (x_shift - 1));
 +
 +      for (i = 0; i < src_w; ) {
 +              curr_x_coeff = 1;
 +              get_pixel(tmp_pixel, *src_p, cf);
 +              i++;
 +              for (l = 0; l < x_array_size; l++) {
 +                      x_column_num = x_coeff[curr_x_coeff++];
 +                      curr_pixel.red = 0;
 +                      curr_pixel.green = 0;
 +                      curr_pixel.blue = 0;
 +                      for (m = 0; m < x_column_num - 1; m++) {
 +                              curr_pixel.red += tmp_pixel.red
 +                                      * x_coeff[curr_x_coeff];
 +                              curr_pixel.green += tmp_pixel.green
 +                                      * x_coeff[curr_x_coeff];
 +                              curr_pixel.blue += tmp_pixel.blue
 +                                      * x_coeff[curr_x_coeff];
 +                              curr_x_coeff++;
 +                              get_pixel(tmp_pixel, *src_p, cf);
 +                              i++;
 +                      }
 +                      curr_pixel.red += tmp_pixel.red * x_coeff[curr_x_coeff];
 +                      curr_pixel.green += tmp_pixel.green
 +                              * x_coeff[curr_x_coeff];
 +                      curr_pixel.blue += tmp_pixel.blue
 +                              * x_coeff[curr_x_coeff];
 +                      curr_x_coeff++;
 +                      curr_pixel.red = (curr_pixel.red + rnd) >> x_shift;
 +                      curr_pixel.green = (curr_pixel.green + rnd) >> x_shift;
 +                      curr_pixel.blue = (curr_pixel.blue + rnd) >> x_shift;
 +                      row_buffer[k].red += curr_pixel.red * y_coeff;
 +                      row_buffer[k].green += curr_pixel.green * y_coeff;
 +                      row_buffer[k].blue += curr_pixel.blue * y_coeff;
 +                      k++;
 +              }
 +      }
 +}
 +
 +static inline void
 +scale_x_up(enum splash_color_format cf, int src_w,
 +         unsigned char **src_p, u32 *x_coeff,
 +         u32 x_shift,  u32 y_coeff, struct pixel *row_buffer)
 +{
 +      u32 curr_x_coeff = 1;
 +      struct pixel curr_pixel, tmp_pixel;
 +      u32 x_array_size = x_coeff[0];
 +      int x_column_num;
 +      int i;
 +      int l, m;
 +      int k = 0;
 +      u32 rnd = (1 << (x_shift - 1));
 +
 +      for (i = 0; i < src_w;) {
 +              curr_x_coeff = 1;
 +              get_pixel(tmp_pixel, *src_p, cf);
 +              i++;
 +              for (l = 0; l < x_array_size - 1; l++) {
 +                      x_column_num = x_coeff[curr_x_coeff++];
 +                      for (m = 0; m < x_column_num; m++) {
 +                              row_buffer[k].red += tmp_pixel.red * y_coeff;
 +                              row_buffer[k].green += tmp_pixel.green * y_coeff;
 +                              row_buffer[k].blue += tmp_pixel.blue * y_coeff;
 +                              k++;
 +                      }
 +                      curr_pixel.red = tmp_pixel.red * x_coeff[curr_x_coeff];
 +                      curr_pixel.green = tmp_pixel.green
 +                              * x_coeff[curr_x_coeff];
 +                      curr_pixel.blue = tmp_pixel.blue * x_coeff[curr_x_coeff];
 +                      curr_x_coeff++;
 +                      get_pixel(tmp_pixel, *src_p, cf);
 +                      i++;
 +                      row_buffer[k].red += ((curr_pixel.red
 +                                             + (tmp_pixel.red
 +                                                * x_coeff[curr_x_coeff])
 +                                             + rnd) >> x_shift) * y_coeff;
 +                      row_buffer[k].green += ((curr_pixel.green
 +                                               + (tmp_pixel.green
 +                                                  * x_coeff[curr_x_coeff])
 +                                               + rnd) >> x_shift) * y_coeff;
 +                      row_buffer[k].blue += ((curr_pixel.blue
 +                                              + (tmp_pixel.blue
 +                                                 * x_coeff[curr_x_coeff])
 +                                              + rnd) >> x_shift) * y_coeff;
 +                      k++;
 +                      curr_x_coeff++;
 +              }
 +              for (m = 0; m < x_coeff[curr_x_coeff]; m++) {
 +                      row_buffer[k].red += tmp_pixel.red * y_coeff;
 +                      row_buffer[k].green += tmp_pixel.green * y_coeff;
 +                      row_buffer[k].blue += tmp_pixel.blue * y_coeff;
 +                      k++;
 +              }
 +      }
 +}
 +
 +static int scale_y_down(unsigned char *src, unsigned char *dst,
 +                      enum splash_color_format cf,
 +                      int src_w, int src_h, int dst_w, int dst_h)
 +{
 +      int octpp = splash_octpp(cf);
 +      int src_x_bytes = octpp * ((src_w + SPLASH_ALIGN) & ~SPLASH_ALIGN);
 +      int dst_x_bytes = octpp * ((dst_w + SPLASH_ALIGN) & ~SPLASH_ALIGN);
 +      int j;
 +      struct pixel *row_buffer;
 +      u32 x_shift, y_shift;
 +      u32 *x_coeff;
 +      u32 *y_coeff;
 +      u32 curr_y_coeff = 1;
 +      unsigned char *src_p;
 +      unsigned char *src_p_line = src;
 +      char *dst_p_line;
 +      int r, s;
 +      int y_array_rows;
 +      int y_column_num;
 +      int k;
 +      u32 rnd;
 +      int xup;
 +
 +      row_buffer = vmalloc(sizeof(struct pixel)
 +                                           * (dst_w + 1));
 +      x_coeff = do_coefficients(src_w, dst_w, &x_shift);
 +      y_coeff = do_coefficients(src_h, dst_h, &y_shift);
 +      if (!row_buffer || !x_coeff || !y_coeff) {
 +              vfree(row_buffer);
 +              vfree(x_coeff);
 +              vfree(y_coeff);
 +              return -ENOMEM;
 +      }
 +      y_array_rows = y_coeff[0];
 +      rnd = (1 << (y_shift - 1));
 +      xup = (src_w <= dst_w) ? 1 : 0;
 +
 +      dst_p_line = dst;
 +
 +      for (j = 0; j < src_h;) {
 +              curr_y_coeff = 1;
 +              for (r = 0; r < y_array_rows; r++) {
 +                      y_column_num = y_coeff[curr_y_coeff++];
 +                      for (k = 0; k < dst_w + 1; k++) {
 +                              row_buffer[k].red = 0;
 +                              row_buffer[k].green = 0;
 +                              row_buffer[k].blue = 0;
 +                      }
 +                      src_p = src_p_line;
 +                      if (xup)
 +                              scale_x_up(cf,  src_w, &src_p, x_coeff,
 +                                         x_shift, y_coeff[curr_y_coeff],
 +                                         row_buffer);
 +                      else
 +                              scale_x_down(cf,  src_w, &src_p, x_coeff,
 +                                           x_shift, y_coeff[curr_y_coeff],
 +                                           row_buffer);
 +                      curr_y_coeff++;
 +                      for (s = 1; s < y_column_num; s++) {
 +                              src_p = src_p_line = src_p_line + src_x_bytes;
 +                              j++;
 +                              if (xup)
 +                                      scale_x_up(cf,  src_w, &src_p,
 +                                                 x_coeff, x_shift,
 +                                                 y_coeff[curr_y_coeff],
 +                                                 row_buffer);
 +                              else
 +                                      scale_x_down(cf,  src_w, &src_p,
 +                                                   x_coeff, x_shift,
 +                                                   y_coeff[curr_y_coeff],
 +                                                   row_buffer);
 +                              curr_y_coeff++;
 +                      }
 +                      for (k = 0; k < dst_w; k++) {
 +                              row_buffer[k].red = (row_buffer[k].red + rnd)
 +                                      >> y_shift;
 +                              row_buffer[k].green = (row_buffer[k].green
 +                                                     + rnd)
 +                                      >> y_shift;
 +                              row_buffer[k].blue = (row_buffer[k].blue + rnd)
 +                                      >> y_shift;
 +                              put_pixel(row_buffer[k], dst, cf);
 +                      }
 +                      dst = dst_p_line = dst_p_line + dst_x_bytes;
 +              }
 +              src_p_line = src_p_line + src_x_bytes;
 +              j++;
 +      }
 +      vfree(row_buffer);
 +      vfree(x_coeff);
 +      vfree(y_coeff);
 +      return 0;
 +}
 +
 +static int scale_y_up(unsigned char *src, unsigned char *dst,
 +                    enum splash_color_format cf,
 +                    int src_w, int src_h, int dst_w, int dst_h)
 +{
 +      int octpp = splash_octpp(cf);
 +      int src_x_bytes = octpp * ((src_w + SPLASH_ALIGN) & ~SPLASH_ALIGN);
 +      int dst_x_bytes = octpp * ((dst_w + SPLASH_ALIGN) & ~SPLASH_ALIGN);
 +      int j;
 +      u32 x_shift, y_shift;
 +      u32 *x_coeff;
 +      u32 *y_coeff;
 +      struct pixel *row_buf_list[2];
 +      struct pixel *row_buffer;
 +      u32 curr_y_coeff = 1;
 +      unsigned char *src_p;
 +      unsigned char *src_p_line = src;
 +      char *dst_p_line;
 +      int r, s;
 +      int y_array_rows;
 +      int y_column_num;
 +      int k;
 +      u32 rnd;
 +      int bi;
 +      int xup;
 +      int writes;
 +
 +      x_coeff = do_coefficients(src_w, dst_w, &x_shift);
 +      y_coeff = do_coefficients(src_h, dst_h, &y_shift);
 +      row_buf_list[0] = vmalloc(2 * sizeof(struct pixel)
 +                                                * (dst_w + 1));
 +      if (!row_buf_list[0] || !x_coeff || !y_coeff) {
 +              vfree(row_buf_list[0]);
 +              vfree(x_coeff);
 +              vfree(y_coeff);
 +              return -ENOMEM;
 +      }
 +      row_buf_list[1] = row_buf_list[0] + (dst_w + 1);
 +
 +      y_array_rows = y_coeff[0];
 +      rnd = (1 << (y_shift - 1));
 +      bi = 1;
 +      xup = (src_w <= dst_w) ? 1 : 0;
 +      writes = 0;
 +
 +      dst_p_line = dst;
 +      src_p = src_p_line;
 +
 +      row_buffer = row_buf_list[0];
 +
 +      for (j = 0; j < src_h;) {
 +              memset(row_buf_list[0], 0, (2 * sizeof(struct pixel)
 +                                          * (dst_w + 1)));
 +              curr_y_coeff = 1;
 +              if (xup)
 +                      scale_x_up(cf,  src_w, &src_p, x_coeff,
 +                                 x_shift, 1, row_buffer);
 +              else
 +                      scale_x_down(cf,  src_w, &src_p, x_coeff, x_shift, 1,
 +                                   row_buffer);
 +              src_p = src_p_line = src_p_line + src_x_bytes;
 +              j++;
 +              for (r = 0; r < y_array_rows - 1; r++) {
 +                      struct pixel *old_row_buffer = row_buffer;
 +                      u32 prev_y_coeff_val;
 +
 +                      y_column_num = y_coeff[curr_y_coeff];
 +                      for (s = 0; s < y_column_num; s++) {
 +                              for (k = 0; k < dst_w; k++)
 +                                      put_pixel(row_buffer[k], dst, cf);
 +                              dst = dst_p_line = dst_p_line + dst_x_bytes;
 +                              writes++;
 +                      }
 +                      curr_y_coeff++;
 +                      row_buffer = row_buf_list[(bi++) % 2];
 +                      prev_y_coeff_val = y_coeff[curr_y_coeff++];
 +                      if (xup)
 +                              scale_x_up(cf,  src_w, &src_p, x_coeff,
 +                                         x_shift, 1, row_buffer);
 +                      else
 +                              scale_x_down(cf,  src_w, &src_p, x_coeff,
 +                                           x_shift, 1, row_buffer);
 +                      src_p = src_p_line = src_p_line + src_x_bytes;
 +                      j++;
 +                      for (k = 0; k < dst_w; k++) {
 +                              struct pixel pix;
 +                              pix.red = ((old_row_buffer[k].red
 +                                          * prev_y_coeff_val)
 +                                         + (row_buffer[k].red
 +                                            * y_coeff[curr_y_coeff])
 +                                         + rnd) >> y_shift;
 +                              pix.green = ((old_row_buffer[k].green
 +                                            * prev_y_coeff_val)
 +                                           + (row_buffer[k].green
 +                                              * y_coeff[curr_y_coeff])
 +                                           + rnd) >> y_shift;
 +                              pix.blue = ((old_row_buffer[k].blue
 +                                           * prev_y_coeff_val)
 +                                          + (row_buffer[k].blue
 +                                             * y_coeff[curr_y_coeff])
 +                                          + rnd) >> y_shift;
 +                              old_row_buffer[k].red = 0;
 +                              old_row_buffer[k].green = 0;
 +                              old_row_buffer[k].blue = 0;
 +                              put_pixel(pix, dst, cf);
 +                      }
 +                      dst = dst_p_line = dst_p_line + dst_x_bytes;
 +                      writes++;
 +                      curr_y_coeff++;
 +              }
 +              for (r = 0; r < y_coeff[curr_y_coeff]; r++) {
 +                      for (k = 0; k < dst_w; k++)
 +                              put_pixel(row_buffer[k], dst, cf);
 +
 +                      dst = dst_p_line = dst_p_line + dst_x_bytes;
 +                      writes++;
 +              }
 +      }
 +      vfree(row_buf_list[0]);
 +      vfree(x_coeff);
 +      vfree(y_coeff);
 +
 +      return 0;
 +}
 +
 +static int jpeg_get(unsigned char *buf, unsigned char *pic,
 +                  int width, int height, enum splash_color_format cf,
 +                  struct jpeg_decdata *decdata)
 +{
 +      int my_width, my_height;
 +      int err;
 +      int octpp = splash_octpp(cf);
 +
 +      jpeg_get_size(buf, &my_width, &my_height);
 +
 +      if (my_height != height || my_width != width) {
 +              int my_size = ((my_width + 15) & ~15)
 +                  * ((my_height + 15) & ~15) * octpp;
 +              unsigned char *mem = vmalloc(my_size);
 +              if (!mem)
 +                      return 17;
 +              err = jpeg_decode(buf, mem, ((my_width + 15) & ~15),
 +                                ((my_height + 15) & ~15), cf, decdata);
 +              if (err) {
 +                      vfree(mem);
 +                      return err;
 +              }
 +              printk(KERN_INFO
 +                     "bootsplash: scaling image from %dx%d to %dx%d\n",
 +                     my_width, my_height, width, height);
 +              if (my_height <= height)
 +                      err = scale_y_up(mem, pic, cf, my_width, my_height,
 +                                       ((width + 15) & ~15),
 +                                       ((height + 15) & ~15));
 +              else
 +                      err = scale_y_down(mem, pic, cf, my_width, my_height,
 +                                         ((width + 15) & ~15),
 +                                         ((height + 15) & ~15));
 +              vfree(mem);
 +              if (err < 0)
 +                      return 17;
 +      } else {
 +              err = jpeg_decode(buf, pic, ((width + 15) & ~15),
 +                                ((height + 15) & ~15), cf, decdata);
 +              if (err)
 +                      return err;
 +      }
 +      return 0;
 +}
index d902a10,0000000..2d89dde
mode 100644,000000..100644
--- /dev/null
@@@ -1,518 -1,0 +1,517 @@@
 +/*
 + *    linux/drivers/video/bootsplash/render.c - splash screen render functions.
 + */
 +
 +#include <linux/module.h>
 +#include <linux/types.h>
 +#include <linux/fb.h>
 +#include <linux/vt_kern.h>
 +#include <linux/selection.h>
 +#include <asm/irq.h>
- #include <asm/system.h>
 +
 +#include "../console/fbcon.h"
 +#include <linux/bootsplash.h>
 +
 +#ifndef DEBUG
 +# define SPLASH_DEBUG(fmt, args...)
 +#else
 +# define SPLASH_DEBUG(fmt, args...) \
 +      printk(KERN_WARNING "%s: " fmt "\n", __func__, ##args)
 +#endif
 +
 +/* fake a region sync */
 +void splash_sync_region(struct fb_info *info, int x, int y,
 +                      int width, int height)
 +{
 +      struct splash_data *sd = info->splash_data;
 +      if (sd && sd->need_sync) {
 +              /* issue a fake copyarea (copy to the very same position)
 +               * for marking the dirty region; this is required for Xen fb
 +               * (bnc#739020)
 +               */
 +              struct fb_copyarea area;
 +              area.sx = area.dx = x;
 +              area.sy = area.dy = y;
 +              area.width = width;
 +              area.height = height;
 +              info->fbops->fb_copyarea(info, &area);
 +      }
 +}
 +
 +void splash_putcs(struct vc_data *vc, struct fb_info *info,
 +                 const unsigned short *s, int count, int ypos, int xpos)
 +{
 +      struct splash_data *sd;
 +      unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
 +      int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
 +      int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;
 +      union pt src;
 +      union pt dst, splashsrc;
 +      unsigned int d, x, y;
 +      u32 dd, fgx, bgx;
 +      u16 c = scr_readw(s);
 +      int fg_color, bg_color, transparent;
 +      int n;
 +      int octpp = (info->var.bits_per_pixel + 1) >> 3;
 +      int drawn_width;
 +
 +      if (!oops_in_progress
 +          && (console_blanked || info->splash_data->splash_dosilent))
 +              return;
 +      sd = info->splash_data;
 +
 +      fg_color = attr_fgcol(fgshift, c);
 +      bg_color = attr_bgcol(bgshift, c);
 +      transparent = sd->imgd->splash_color == bg_color;
 +      xpos = xpos * vc->vc_font.width + sd->imgd->splash_text_xo;
 +      ypos = ypos * vc->vc_font.height + sd->imgd->splash_text_yo;
 +      splashsrc.ub = (u8 *)(sd->pic->splash_pic
 +                            + ypos * sd->pic->splash_pic_stride
 +                            + xpos * octpp);
 +      dst.ub = (u8 *)(info->screen_base
 +                      + ypos * info->fix.line_length
 +                      + xpos * octpp);
 +      fgx = ((u32 *)info->pseudo_palette)[fg_color];
 +      if (transparent && sd->imgd->splash_color == 15) {
 +              if (fgx == 0xffea)
 +                      fgx = 0xfe4a;
 +              else if (fgx == 0x57ea)
 +                      fgx = 0x0540;
 +              else if (fgx == 0xffff)
 +                      fgx = 0x52aa;
 +      }
 +      bgx = ((u32 *)info->pseudo_palette)[bg_color];
 +      d = 0;
 +      drawn_width = 0;
 +      while (count--) {
 +              c = scr_readw(s++);
 +              src.ub = vc->vc_font.data
 +                      + ((c & charmask)
 +                         * vc->vc_font.height
 +                         * ((vc->vc_font.width + 7) >> 3));
 +              for (y = 0; y < vc->vc_font.height; y++) {
 +                      for (x = 0; x < vc->vc_font.width; ) {
 +                              if ((x & 7) == 0)
 +                                      d = *src.ub++;
 +                              switch (octpp) {
 +                              case 2:
 +                                      if (d & 0x80)
 +                                              dd = fgx;
 +                                      else
 +                                              dd = (transparent ?
 +                                                    *splashsrc.us : bgx);
 +                                      splashsrc.us += 1;
 +                                      if (d & 0x40)
 +                                              dd |= fgx << 16;
 +                                      else
 +                                              dd |= (transparent ? *splashsrc.us : bgx) << 16;
 +                                      splashsrc.us += 1;
 +                                      d <<= 2;
 +                                      x += 2;
 +                                      fb_writel(dd, dst.ul);
 +                                      dst.ul += 1;
 +                                      break;
 +                              case 3:
 +                                      for (n = 0; n <= 16; n += 8) {
 +                                              if (d & 0x80)
 +                                                      dd = (fgx >> n) & 0xff;
 +                                              else
 +                                                      dd = (transparent ? *splashsrc.ul : ((bgx >> n) & 0xff));
 +                                              splashsrc.ub += 1;
 +                                              fb_writeb(dd, dst.ub);
 +                                              dst.ub += 1;
 +                                      }
 +                                      d <<= 1;
 +                                      x += 1;
 +                                      break;
 +                              case 4:
 +                                      if (d & 0x80)
 +                                              dd = fgx;
 +                                      else
 +                                              dd = (transparent ? *splashsrc.ul : bgx);
 +                                      splashsrc.ul += 1;
 +                                      d <<= 1;
 +                                      x += 1;
 +                                      fb_writel(dd, dst.ul);
 +                                      dst.ul += 1;
 +                                      break;
 +                              }
 +                      }
 +                      dst.ub += info->fix.line_length
 +                              - vc->vc_font.width * octpp;
 +                      splashsrc.ub += sd->pic->splash_pic_stride
 +                              - vc->vc_font.width * octpp;
 +              }
 +              dst.ub -= info->fix.line_length * vc->vc_font.height
 +                      - vc->vc_font.width * octpp;
 +              splashsrc.ub -= sd->pic->splash_pic_stride * vc->vc_font.height
 +                      - vc->vc_font.width * octpp;
 +              drawn_width += vc->vc_font.width;
 +      }
 +      splash_sync_region(info, xpos, ypos, drawn_width, vc->vc_font.height);
 +}
 +
 +static void splash_renderc(struct fb_info *info,
 +                         int fg_color, int bg_color,
 +                         u8 *src,
 +                         int ypos, int xpos,
 +                         int height, int width)
 +{
 +      struct splash_data *sd;
 +      int transparent;
 +      u32 dd, fgx, bgx;
 +      union pt dst, splashsrc;
 +      unsigned int d, x, y;
 +      int n;
 +      int octpp = (info->var.bits_per_pixel + 1) >> 3;
 +
 +      if (!oops_in_progress
 +          && (console_blanked || info->splash_data->splash_dosilent))
 +              return;
 +
 +      sd = info->splash_data;
 +
 +      transparent = sd->imgd->splash_color == bg_color;
 +      splashsrc.ub = (u8 *)(sd->pic->splash_pic
 +                           + ypos * sd->pic->splash_pic_stride
 +                           + xpos * octpp);
 +      dst.ub = (u8 *)(info->screen_base
 +                     + ypos * info->fix.line_length
 +                     + xpos * octpp);
 +      fgx = ((u32 *)info->pseudo_palette)[fg_color];
 +      if (transparent && (sd->imgd->splash_color == 15)) {
 +              if (fgx == 0xffea)
 +                      fgx = 0xfe4a;
 +              else if (fgx == 0x57ea)
 +                      fgx = 0x0540;
 +              else if (fgx == 0xffff)
 +                      fgx = 0x52aa;
 +      }
 +      bgx = ((u32 *)info->pseudo_palette)[bg_color];
 +      d = 0;
 +      for (y = 0; y < height; y++) {
 +              for (x = 0; x < width; ) {
 +                      if ((x & 7) == 0)
 +                              d = *src++;
 +                      switch (octpp) {
 +                      case 2:
 +                              if (d & 0x80)
 +                                      dd = fgx;
 +                              else
 +                                      dd = (transparent ? *splashsrc.us : bgx);
 +                              splashsrc.us += 1;
 +                              if (d & 0x40)
 +                                      dd |= fgx << 16;
 +                              else
 +                                      dd |= (transparent ? *splashsrc.us : bgx) << 16;
 +                              splashsrc.us += 1;
 +                              d <<= 2;
 +                              x += 2;
 +                              fb_writel(dd, dst.ul);
 +                              dst.ul += 1;
 +                              break;
 +                      case 3:
 +                              for (n = 0; n <= 16; n += 8) {
 +                                      if (d & 0x80)
 +                                              dd = (fgx >> n) & 0xff;
 +                                      else
 +                                              dd = (transparent ? *splashsrc.ub : bgx);
 +                                      splashsrc.ub += 1;
 +                                      fb_writeb(dd, dst.ub);
 +                                      dst.ub += 1;
 +                              }
 +                              d <<= 1;
 +                              x += 1;
 +                              break;
 +                      case 4:
 +                              if (d & 0x80)
 +                                      dd = fgx;
 +                              else
 +                                      dd = (transparent ? *splashsrc.ul : bgx);
 +                              splashsrc.ul += 1;
 +                              d <<= 1;
 +                              x += 1;
 +                              fb_writel(dd, dst.ul);
 +                              dst.ul += 1;
 +                              break;
 +                      }
 +              }
 +              dst.ub += info->fix.line_length - width * octpp;
 +              splashsrc.ub += sd->pic->splash_pic_stride - width * octpp;
 +      }
 +      splash_sync_region(info, xpos, ypos, width, height);
 +}
 +
 +void splashcopy(u8 *dst, u8 *src, int height, int width,
 +              int dstbytes, int srcbytes, int octpp)
 +{
 +      int i;
 +
 +      width *= octpp;
 +      while (height-- > 0) {
 +              union pt p, q;
 +              p.ul = (u32 *)dst;
 +              q.ul = (u32 *)src;
 +              for (i = 0; i < width / 4; i++)
 +                      fb_writel(*q.ul++, p.ul++);
 +              if (width & 2)
 +                      fb_writew(*q.us++, p.us++);
 +              if (width & 1)
 +                      fb_writeb(*q.ub, p.ub);
 +              dst += dstbytes;
 +              src += srcbytes;
 +      }
 +}
 +
 +static void splashset(u8 *dst, int height, int width,
 +                    int dstbytes, u32 bgx, int octpp) {
 +      int i;
 +
 +      width *= octpp;
 +      if (octpp == 2)
 +              bgx |= bgx << 16;
 +      while (height-- > 0) {
 +              union pt p;
 +              p.ul = (u32 *)dst;
 +              if (!(octpp & 1)) {
 +                      for (i = 0; i < width / 4; i++)
 +                              fb_writel(bgx, p.ul++);
 +                      if (width & 2)
 +                              fb_writew(bgx, p.us++);
 +                      if (width & 1)
 +                              fb_writeb(bgx, p.ub);
 +                      dst += dstbytes;
 +              } else { /* slow! */
 +                      for (i = 0; i < width; i++)
 +                              fb_writeb((bgx >> ((i % 3) * 8)) & 0xff,
 +                                        p.ub++);
 +              }
 +      }
 +}
 +
 +static void splashfill(struct fb_info *info, int sy, int sx,
 +                     int height, int width) {
 +      int octpp = (info->var.bits_per_pixel + 1) >> 3;
 +      struct splash_data *sd = info->splash_data;
 +
 +      splashcopy((u8 *)(info->screen_base
 +                        + sy * info->fix.line_length + sx * octpp),
 +                 (u8 *)(sd->pic->splash_pic
 +                        + sy * sd->pic->splash_pic_stride
 +                        + sx * octpp),
 +                 height, width, info->fix.line_length,
 +                 sd->pic->splash_pic_stride,
 +                 octpp);
 +      splash_sync_region(info, sx, sy, width, height);
 +}
 +
 +void splash_clear(struct vc_data *vc, struct fb_info *info, int sy,
 +                      int sx, int height, int width)
 +{
 +      struct splash_data *sd;
 +      int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
 +      int bg_color = attr_bgcol_ec(bgshift, vc, info);
 +      int transparent;
 +      int octpp = (info->var.bits_per_pixel + 1) >> 3;
 +      u32 bgx;
 +      u8 *dst;
 +
 +      if (!oops_in_progress
 +          && (console_blanked || info->splash_data->splash_dosilent))
 +              return;
 +
 +      sd = info->splash_data;
 +
 +      transparent = sd->imgd->splash_color == bg_color;
 +
 +      sy = sy * vc->vc_font.height + sd->imgd->splash_text_yo;
 +      sx = sx * vc->vc_font.width + sd->imgd->splash_text_xo;
 +      height *= vc->vc_font.height;
 +      width *= vc->vc_font.width;
 +      if (transparent) {
 +              splashfill(info, sy, sx, height, width);
 +              return;
 +      }
 +      dst = (u8 *)(info->screen_base
 +                   + sy * info->fix.line_length
 +                   + sx * octpp);
 +      bgx = ((u32 *)info->pseudo_palette)[bg_color];
 +      splashset(dst,
 +                height, width,
 +                info->fix.line_length,
 +                bgx,
 +                (info->var.bits_per_pixel + 1) >> 3);
 +      splash_sync_region(info, sx, sy, width, height);
 +}
 +
 +void splash_bmove(struct vc_data *vc, struct fb_info *info, int sy,
 +              int sx, int dy, int dx, int height, int width)
 +{
 +      struct splash_data *sd;
 +      struct fb_copyarea area;
 +
 +      if (!oops_in_progress
 +          && (console_blanked || info->splash_data->splash_dosilent))
 +              return;
 +
 +      sd = info->splash_data;
 +
 +      area.sx = sx * vc->vc_font.width;
 +      area.sy = sy * vc->vc_font.height;
 +      area.dx = dx * vc->vc_font.width;
 +      area.dy = dy * vc->vc_font.height;
 +      area.sx += sd->imgd->splash_text_xo;
 +      area.sy += sd->imgd->splash_text_yo;
 +      area.dx += sd->imgd->splash_text_xo;
 +      area.dy += sd->imgd->splash_text_yo;
 +      area.height = height * vc->vc_font.height;
 +      area.width = width * vc->vc_font.width;
 +
 +      info->fbops->fb_copyarea(info, &area);
 +}
 +
 +void splash_clear_margins(struct vc_data *vc, struct fb_info *info,
 +                              int bottom_only)
 +{
 +      struct splash_data *sd;
 +      unsigned int tw = vc->vc_cols*vc->vc_font.width;
 +      unsigned int th = vc->vc_rows*vc->vc_font.height;
 +      SPLASH_DEBUG();
 +
 +      if (!oops_in_progress
 +          && (console_blanked || info->splash_data->splash_dosilent))
 +              return;
 +
 +      sd = info->splash_data;
 +
 +      if (!bottom_only) {
 +              /* top margin */
 +              splashfill(info,
 +                         0,
 +                         0,
 +                         sd->imgd->splash_text_yo,
 +                         info->var.xres);
 +              /* left margin */
 +              splashfill(info,
 +                         sd->imgd->splash_text_yo,
 +                         0,
 +                         th,
 +                         sd->imgd->splash_text_xo);
 +              /* right margin */
 +              splashfill(info,
 +                         sd->imgd->splash_text_yo,
 +                         sd->imgd->splash_text_xo + tw,
 +                         th,
 +                         info->var.xres - sd->imgd->splash_text_xo - tw);
 +      }
 +      splashfill(info,
 +                 sd->imgd->splash_text_yo + th,
 +                 0,
 +                 info->var.yres - sd->imgd->splash_text_yo - th,
 +                 info->var.xres);
 +}
 +
 +int splash_cursor(struct fb_info *info, struct fb_cursor *cursor)
 +{
 +      struct splash_data *sd;
 +      int i;
 +      unsigned int dsize, s_pitch;
 +
 +      if (info->state != FBINFO_STATE_RUNNING)
 +              return 0;
 +
 +      sd = info->splash_data;
 +
 +      s_pitch = (cursor->image.width + 7) >> 3;
 +      dsize = s_pitch * cursor->image.height;
 +      if (cursor->enable) {
 +              switch (cursor->rop) {
 +              case ROP_XOR:
 +                      for (i = 0; i < dsize; i++)
 +                              info->fb_cursordata[i] = cursor->image.data[i]
 +                                      ^ cursor->mask[i];
 +                      break;
 +              case ROP_COPY:
 +              default:
 +                      for (i = 0; i < dsize; i++)
 +                              info->fb_cursordata[i] = cursor->image.data[i]
 +                                      & cursor->mask[i];
 +                      break;
 +              }
 +      } else if (info->fb_cursordata != cursor->image.data)
 +              memcpy(info->fb_cursordata, cursor->image.data, dsize);
 +      cursor->image.data = info->fb_cursordata;
 +      splash_renderc(info, cursor->image.fg_color, cursor->image.bg_color,
 +                     (u8 *)info->fb_cursordata,
 +                     cursor->image.dy + sd->imgd->splash_text_yo,
 +                     cursor->image.dx + sd->imgd->splash_text_xo,
 +                     cursor->image.height,
 +                     cursor->image.width);
 +      return 0;
 +}
 +
 +void splash_bmove_redraw(struct vc_data *vc, struct fb_info *info,
 +                       int y, int sx, int dx, int width)
 +{
 +      struct splash_data *sd;
 +      unsigned short *d = (unsigned short *) (vc->vc_origin
 +                                              + vc->vc_size_row * y
 +                                              + dx * 2);
 +      unsigned short *s = d + (dx - sx);
 +      unsigned short *start = d;
 +      unsigned short *ls = d;
 +      unsigned short *le = d + width;
 +      unsigned short c;
 +      int x = dx;
 +      unsigned short attr = 1;
 +
 +      if (console_blanked || info->splash_data->splash_dosilent)
 +              return;
 +
 +      sd = info->splash_data;
 +
 +      do {
 +              c = scr_readw(d);
 +              if (attr != (c & 0xff00)) {
 +                      attr = c & 0xff00;
 +                      if (d > start) {
 +                              splash_putcs(vc, info, start, d - start, y, x);
 +                              x += d - start;
 +                              start = d;
 +                      }
 +              }
 +              if (s >= ls && s < le && c == scr_readw(s)) {
 +                      if (d > start) {
 +                              splash_putcs(vc, info, start, d - start, y, x);
 +                              x += d - start + 1;
 +                              start = d + 1;
 +                      } else {
 +                              x++;
 +                              start++;
 +                      }
 +              }
 +              s++;
 +              d++;
 +      } while (d < le);
 +      if (d > start)
 +              splash_putcs(vc, info, start, d - start, y, x);
 +}
 +
 +void splash_blank(struct vc_data *vc, struct fb_info *info, int blank)
 +{
 +      SPLASH_DEBUG();
 +
 +      if (blank) {
 +              splashset((u8 *)info->screen_base,
 +                        info->var.yres, info->var.xres,
 +                        info->fix.line_length,
 +                        0,
 +                        (info->var.bits_per_pixel + 1) >> 3);
 +              splash_sync_region(info, 0, 0, info->var.xres, info->var.yres);
 +      } else {
 +              /* splash_prepare(vc, info);  *//* do we really need this? */
 +              splash_clear_margins(vc, info, 0);
 +              /* no longer needed, done in fbcon_blank */
 +              /* update_screen(vc->vc_num); */
 +      }
 +}
  #include <linux/crc32.h> /* For counting font checksums */
  #include <asm/fb.h>
  #include <asm/irq.h>
- #include <asm/system.h>
  
  #include "fbcon.h"
 +#include <linux/bootsplash.h>
  
  #ifdef FBCONDEBUG
  #  define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
Simple merge
diff --cc fs/nfs/dir.c
Simple merge
diff --cc fs/nfs/inode.c
Simple merge
diff --cc fs/super.c
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -235,8 -236,10 +236,11 @@@ void             rpc_wake_up_queued_task(struct rp
                                        struct rpc_task *);
  void          rpc_wake_up(struct rpc_wait_queue *);
  struct rpc_task *rpc_wake_up_next(struct rpc_wait_queue *);
+ struct rpc_task *rpc_wake_up_first(struct rpc_wait_queue *,
+                                       bool (*)(struct rpc_task *, void *),
+                                       void *);
  void          rpc_wake_up_status(struct rpc_wait_queue *, int);
 +void          rpc_wake_up_softconn_status(struct rpc_wait_queue *, int);
  int           rpc_queue_empty(struct rpc_wait_queue *);
  void          rpc_delay(struct rpc_task *, unsigned long);
  void *                rpc_malloc(struct rpc_task *, size_t);
Simple merge
Simple merge
diff --cc init/Kconfig
Simple merge
diff --cc init/main.c
Simple merge
Simple merge
diff --cc kernel/Makefile
Simple merge
diff --cc kernel/ksysfs.c
Simple merge
diff --cc kernel/module.c
Simple merge
diff --cc kernel/printk.c
Simple merge
diff --cc kernel/sysctl.c
Simple merge
Simple merge
Simple merge
diff --cc mm/page_alloc.c
Simple merge
diff --cc mm/truncate.c
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge