YABEL update

- drop x86emu + old biosemu in favor of YABEL
- Add YABEL_DIRECTHW to get the old biosemu behavior
- add support for vesa console using YABEL
- add coreboot table entry with console information
- add bootsplash support (reads /bootsplash.jpg from CBFS)

Signed-off-by: Stefan Reinauer <stepan@coresystems.de>
Acked-by: Pattrick Hueper <phueper@hueper.net>



git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5135 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
Stefan Reinauer
2010-02-22 04:33:13 +00:00
committed by Stefan Reinauer
parent 30b90fe4f0
commit d650e9934f
18 changed files with 1507 additions and 817 deletions

View File

@ -148,6 +148,19 @@ static void lb_console(struct lb_header *header)
#endif
}
static void lb_framebuffer(struct lb_header *header)
{
#if defined(CONFIG_BOOTSPLASH) && CONFIG_BOOTSPLASH && CONFIG_COREBOOT_KEEP_FRAMEBUFFER
void fill_lb_framebuffer(struct lb_framebuffer *framebuffer);
struct lb_framebuffer *framebuffer;
framebuffer = (struct lb_framebuffer *)lb_new_record(header);
framebuffer->tag = LB_TAG_FRAMEBUFFER;
framebuffer->size = sizeof(*framebuffer);
fill_lb_framebuffer(framebuffer);
#endif
}
static struct lb_mainboard *lb_mainboard(struct lb_header *header)
{
struct lb_record *rec;
@ -565,6 +578,8 @@ unsigned long write_coreboot_table(
lb_console(head);
/* Record our various random string information */
lb_strings(head);
/* Record our framebuffer */
lb_framebuffer(head);
/* Remember where my valid memory ranges are */
return lb_table_fini(head, 1);

View File

@ -14,4 +14,7 @@
#define cpu_to_be16(x) swab16((x))
#define be16_to_cpu(x) swab16((x))
#define ntohl(x) be32_to_cpu(x)
#define htonl(x) cpu_to_be32(x)
#endif /* _BYTEORDER_H */

View File

@ -1,7 +1,7 @@
##
## This file is part of the coreboot project.
##
## Copyright (C) 2007 coresystems GmbH
## Copyright (C) 2007-2010 coresystems GmbH
## (Written by Stefan Reinauer <stepan@coresystems.de> for coresystems GmbH)
##
## This program is free software; you can redistribute it and/or modify
@ -49,7 +49,7 @@ choice
depends on PCI_ROM_RUN || VGA_ROM_RUN
config PCI_OPTION_ROM_RUN_REALMODE
prompt "Real mode"
prompt "Native mode"
bool
depends on ARCH_X86
help
@ -58,37 +58,60 @@ config PCI_OPTION_ROM_RUN_REALMODE
so this is the fastest, but also the least secure option.
(only works on x86/x64 systems)
config PCI_OPTION_ROM_RUN_X86EMU
prompt "x86emu"
config PCI_OPTION_ROM_RUN_YABEL
prompt "Secure Mode"
bool
help
If you select this option, the x86emu CPU emulator will be used to
execute PCI option ROMs.
When choosing this option, x86emu will pass through all hardware
accesses to memory and IO devices to the underlying memory and IO
addresses. While this option prevents option ROMs from doing dirty
tricks with the CPU (such as installing SMM modules or hypervisors),
they can still access all devices in the system.
Choosing x86emu, option ROM execution is slower than native execution
in real mode, but faster than the full system emulation YABEL
This is the default choice for non-x86 systems.
config PCI_OPTION_ROM_RUN_YABEL
prompt "YABEL"
bool
help
If you select this option, the YABEL system emulator will be used to
execute PCI option ROMs.
YABEL consists of two parts: It uses x86emu for the CPU emulation and
additionally provides a PC system emulation that filters bad device and
memory access (such as PCI config space access to other devices than the
initialized one).
This option best prevents option ROMs from doing dirty tricks with the
This option prevents option ROMs from doing dirty tricks with the
system (such as installing SMM modules or hypervisors), but it is also
significantly slower than the other option ROM initialization methods.
significantly slower than the native option ROM initialization method.
This is the default choice for non-x86 systems.
endchoice
# TODO: Describe better, and/or make a "choice" selection for this.
config YABEL_DEBUG_FLAGS
prompt "Hex value for YABEL debug flags"
hex
default 0x0
depends on PCI_OPTION_ROM_RUN_YABEL
help
Set CONFIG_YABEL_DEBUG_FLAGS is a binary switch that allows you
to select the following items to debug. 1=on 0=off. After you
decide what you want to debug create the binary value, convert to hex
and set the Option (Ex. CONFIG_YABEL_DEBUG_FLAGS = 0x31FF //Debug All).
|-DEBUG_JMP - print info about JMP and RETF opcodes from x86emu
||-DEBUG_TRACE_X86EMU - print _all_ opcodes that are executed by x86emu (WARNING: this will produce a LOT of output)
|||-Currently unused
||||-Currently unused
|||||-Currently unused
||||||-DEBUG_PNP - Print Plug And Play access made by option rom
|||||||-DEBUG_DISK - Print Disk I/O related messages, currently unused
||||||||-DEBUG_PMM - Print messages related to POST Memory Manager (PMM)
|||||||||-DEBUG_VBE - Print messages related to VESA BIOS Extension (VBE) functions
||||||||||-DEBUG_PRINT_INT10 - let INT10 (i.e. character output) calls print messages to Debug output
|||||||||||-DEBUG_INTR - Print messages related to interrupt handling
||||||||||||-DEBUG_CHECK_VMEM_ACCESS - Print messages related to accesse to certain areas of the virtual Memory (e.g. BDA (BIOS Data Area) or Interrupt Vectors)
|||||||||||||-DEBUG_MEM - Print memory access made by option rom (NOTE: this also includes accesses to fetch instructions)
||||||||||||||-DEBUG_IO - Print I/O access made by option rom
11000111111111 - Max Binary Value, Debug All (WARNING: - This could run for hours)
DEBUG_IO 0x0001
DEBUG_MEM 0x0002
DEBUG_CHECK_VMEM_ACCESS 0x0004
DEBUG_INTR 0x0008
DEBUG_PRINT_INT10 0x0010
DEBUG_VBE 0x0020
DEBUG_PMM 0x0040
DEBUG_DISK 0x0080
DEBUG_PNP 0x0100
DEBUG_TRACE_X86EMU 0x1000
DEBUG_JMP 0x2000
See debug.h for values 0 is no debug output, 0x31ff is _verbose_.
config YABEL_PCI_ACCESS_OTHER_DEVICES
prompt "Allow option roms to acces other devices"
bool
@ -102,20 +125,56 @@ config YABEL_PCI_ACCESS_OTHER_DEVICES
config YABEL_VIRTMEM_LOCATION
prompt "Location of YABEL's virtual memory"
hex
depends on EXPERT
depends on PCI_OPTION_ROM_RUN_YABEL && EXPERT
default 0x1000000
help
YABEL requires 1MB memory for its CPU emulation. This memory is
normally located at 16MB.
# TODO: Describe better, and/or make a "choice" selection for this.
config YABEL_DEBUG_FLAGS
prompt "Hex value for YABEL debug flags"
hex
default 0x0
config YABEL_DIRECTHW
prompt "Direct Hardware Access"
bool
depends on PCI_OPTION_ROM_RUN_YABEL
help
See debug.h for values 0 is no debug output, 0x31ff is _verbose_.
YABEL consists of two parts: It uses x86emu for the CPU emulation and
additionally provides a PC system emulation that filters bad device and
memory access (such as PCI config space access to other devices than the
initialized one).
When choosing this option, x86emu will pass through all hardware
accesses to memory and IO devices to the underlying memory and IO
addresses. While this option prevents option ROMs from doing dirty
tricks with the CPU (such as installing SMM modules or hypervisors),
they can still access all devices in the system.
Enable this option for a good compromise between security and speed.
config BOOTSPLASH
prompt "Show graphical bootsplash"
bool
depends on PCI_OPTION_ROM_RUN_YABEL
help
This option shows a graphical bootsplash screen. The grapics are
loaded from the CBFS file bootsplash.jpg
config FRAMEBUFFER_VESA_MODE
prompt "VESA framebuffer video mode"
hex
default 0x117
depends on BOOTSPLASH
help
This option sets the resolution used for the coreboot framebuffer and
bootsplash screen. Set to 0x117 for 1024x768x16. A diligent soul will
some day make this a "choice".
config COREBOOT_KEEP_FRAMEBUFFER
prompt "Keep VESA framebuffer"
bool
depends on BOOTSPLASH
help
This option keeps the framebuffer mode set after coreboot finishes
execution. If this option is enabled, coreboot will pass a framebuffer
entry in its coreboot table and the payload will need a framebuffer
driver. If this option is disabled, coreboot will switch back to
text mode before handing control to a payload.
config CONSOLE_VGA_MULTI
bool

View File

@ -159,6 +159,13 @@ struct lb_console {
uint16_t type;
};
#define LB_TAG_CONSOLE_SERIAL8250 0
#define LB_TAG_CONSOLE_VGA 1
#define LB_TAG_CONSOLE_BTEXT 2
#define LB_TAG_CONSOLE_LOGBUF 3
#define LB_TAG_CONSOLE_SROM 4
#define LB_TAG_CONSOLE_EHCI 5
#define LB_TAG_FORWARD 0x0011
struct lb_forward {
uint32_t tag;
@ -166,12 +173,25 @@ struct lb_forward {
uint64_t forward;
};
#define LB_TAG_CONSOLE_SERIAL8250 0
#define LB_TAG_CONSOLE_VGA 1
#define LB_TAG_CONSOLE_BTEXT 2
#define LB_TAG_CONSOLE_LOGBUF 3
#define LB_TAG_CONSOLE_SROM 4
#define LB_TAG_CONSOLE_EHCI 5
#define LB_TAG_FRAMEBUFFER 0x0012
struct lb_framebuffer {
uint32_t tag;
uint32_t size;
uint64_t physical_address;
uint32_t x_resolution;
uint32_t y_resolution;
uint32_t bytes_per_line;
uint8_t bits_per_pixel;
uint8_t red_mask_pos;
uint8_t red_mask_size;
uint8_t green_mask_pos;
uint8_t green_mask_size;
uint8_t blue_mask_pos;
uint8_t blue_mask_size;
uint8_t reserved_mask_pos;
uint8_t reserved_mask_size;
};
/* The following structures are for the cmos definitions table */
#define LB_TAG_CMOS_OPTION_TABLE 200

View File

@ -26,6 +26,8 @@ initobj-y += lzma.o
obj-$(CONFIG_USBDEBUG_DIRECT) += usbdebug_direct.o
obj-$(CONFIG_COMPRESSED_PAYLOAD_LZMA) += lzma.o
obj-$(CONFIG_BOOTSPLASH) += jpeg.o
ifdef POST_EVALUATION
$(obj)/lib/version.o :: $(obj)/build.h
endif

View File

@ -22,13 +22,7 @@
#include <console/console.h>
#include <cbfs.h>
#include <lib.h>
#ifndef CONFIG_BIG_ENDIAN
#define ntohl(x) ( ((x&0xff)<<24) | ((x&0xff00)<<8) | \
((x&0xff0000) >> 8) | ((x&0xff000000) >> 24) )
#else
#define ntohl(x) (x)
#endif
#include <arch/byteorder.h>
int cbfs_decompress(int algo, void *src, void *dst, int len)
{
@ -213,7 +207,7 @@ void * cbfs_load_stage(const char *name)
void * cbfs_get_file(const char *name)
{
return cbfs_find(name);
return (void *) cbfs_find(name);
}
int cbfs_execute_stage(const char *name)

View File

@ -30,6 +30,11 @@ void set_boot_successful(void)
void boot_successful(void)
{
#if defined(CONFIG_BOOTSPLASH) && CONFIG_BOOTSPLASH && !CONFIG_COREBOOT_KEEP_FRAMEBUFFER
void vbe_textmode_console(void);
vbe_textmode_console();
#endif
/* Remember this was a successful boot */
set_boot_successful();

988
src/lib/jpeg.c Normal file
View File

@ -0,0 +1,988 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2001 by Michael Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
/*
* a tiny jpeg decoder.
*
* written in August 2001 by Michael Schroeder <mls@suse.de>
*
*/
#define __LITTLE_ENDIAN
#include <string.h>
#include "jpeg.h"
#define ISHIFT 11
#define IFIX(a) ((int)((a) * (1 << ISHIFT) + .5))
#define IMULT(a, b) (((a) * (b)) >> ISHIFT)
#define ITOINT(a) ((a) >> ISHIFT)
#ifndef __P
# define __P(x) x
#endif
/* special markers */
#define M_BADHUFF -1
#define M_EOF 0x80
struct in {
unsigned char *p;
unsigned int bits;
int left;
int marker;
int (*func) __P((void *));
void *data;
};
/*********************************/
struct dec_hufftbl;
struct enc_hufftbl;
union hufftblp {
struct dec_hufftbl *dhuff;
struct enc_hufftbl *ehuff;
};
struct scan {
int dc; /* old dc value */
union hufftblp hudc;
union hufftblp huac;
int next; /* when to switch to next scan */
int cid; /* component id */
int hv; /* horiz/vert, copied from comp */
int tq; /* quant tbl, copied from comp */
};
/*********************************/
#define DECBITS 10 /* seems to be the optimum */
struct dec_hufftbl {
int maxcode[17];
int valptr[16];
unsigned char vals[256];
unsigned int llvals[1 << DECBITS];
};
static void decode_mcus __P((struct in *, int *, int, struct scan *, int *));
static int dec_readmarker __P((struct in *));
static void dec_makehuff __P((struct dec_hufftbl *, int *, unsigned char *));
static void setinput __P((struct in *, unsigned char *));
/*********************************/
#undef PREC
#define PREC int
static void idctqtab __P((unsigned char *, PREC *));
static void idct __P((int *, int *, PREC *, PREC, int));
static void scaleidctqtab __P((PREC *, PREC));
/*********************************/
static void initcol __P((PREC[][64]));
static void col221111 __P((int *, unsigned char *, int));
static void col221111_16 __P((int *, unsigned char *, int));
static void col221111_32 __P((int *, unsigned char *, int));
/*********************************/
#define M_SOI 0xd8
#define M_APP0 0xe0
#define M_DQT 0xdb
#define M_SOF0 0xc0
#define M_DHT 0xc4
#define M_DRI 0xdd
#define M_SOS 0xda
#define M_RST0 0xd0
#define M_EOI 0xd9
#define M_COM 0xfe
static unsigned char *datap;
static int getbyte(void)
{
return *datap++;
}
static int getword(void)
{
int c1, c2;
c1 = *datap++;
c2 = *datap++;
return c1 << 8 | c2;
}
struct comp {
int cid;
int hv;
int tq;
};
#define MAXCOMP 4
struct jpginfo {
int nc; /* number of components */
int ns; /* number of scans */
int dri; /* restart interval */
int nm; /* mcus til next marker */
int rm; /* next restart marker */
};
static struct jpginfo info;
static struct comp comps[MAXCOMP];
static struct scan dscans[MAXCOMP];
static unsigned char quant[4][64];
static struct dec_hufftbl dhuff[4];
#define dec_huffdc (dhuff + 0)
#define dec_huffac (dhuff + 2)
static struct in in;
static int readtables(int till)
{
int m, l, i, j, lq, pq, tq;
int tc, th, tt;
for (;;) {
if (getbyte() != 0xff)
return -1;
if ((m = getbyte()) == till)
break;
switch (m) {
case 0xc2:
return 0;
case M_DQT:
lq = getword();
while (lq > 2) {
pq = getbyte();
tq = pq & 15;
if (tq > 3)
return -1;
pq >>= 4;
if (pq != 0)
return -1;
for (i = 0; i < 64; i++)
quant[tq][i] = getbyte();
lq -= 64 + 1;
}
break;
case M_DHT:
l = getword();
while (l > 2) {
int hufflen[16], k;
unsigned char huffvals[256];
tc = getbyte();
th = tc & 15;
tc >>= 4;
tt = tc * 2 + th;
if (tc > 1 || th > 1)
return -1;
for (i = 0; i < 16; i++)
hufflen[i] = getbyte();
l -= 1 + 16;
k = 0;
for (i = 0; i < 16; i++) {
for (j = 0; j < hufflen[i]; j++)
huffvals[k++] = getbyte();
l -= hufflen[i];
}
dec_makehuff(dhuff + tt, hufflen,
huffvals);
}
break;
case M_DRI:
l = getword();
info.dri = getword();
break;
default:
l = getword();
while (l-- > 2)
getbyte();
break;
}
}
return 0;
}
static void dec_initscans(void)
{
int i;
info.nm = info.dri + 1;
info.rm = M_RST0;
for (i = 0; i < info.ns; i++)
dscans[i].dc = 0;
}
static int dec_checkmarker(void)
{
int i;
if (dec_readmarker(&in) != info.rm)
return -1;
info.nm = info.dri;
info.rm = (info.rm + 1) & ~0x08;
for (i = 0; i < info.ns; i++)
dscans[i].dc = 0;
return 0;
}
int jpeg_check_size(unsigned char *buf, int width, int height)
{
datap = buf;
getbyte();
getbyte();
readtables(M_SOF0);
getword();
getbyte();
if (height != getword() || width != getword())
return 0;
return 1;
}
int jpeg_decode(unsigned char *buf, unsigned char *pic,
int width, int height, int depth, struct jpeg_decdata *decdata)
{
int i, j, m, tac, tdc;
int mcusx, mcusy, mx, my;
int max[6];
if (!decdata || !buf || !pic)
return -1;
datap = buf;
if (getbyte() != 0xff)
return ERR_NO_SOI;
if (getbyte() != M_SOI)
return ERR_NO_SOI;
if (readtables(M_SOF0))
return ERR_BAD_TABLES;
getword();
i = getbyte();
if (i != 8)
return ERR_NOT_8BIT;
if (((getword() + 15) & ~15) != height)
return ERR_HEIGHT_MISMATCH;
if (((getword() + 15) & ~15) != width)
return ERR_WIDTH_MISMATCH;
if ((height & 15) || (width & 15))
return ERR_BAD_WIDTH_OR_HEIGHT;
info.nc = getbyte();
if (info.nc > MAXCOMP)
return ERR_TOO_MANY_COMPPS;
for (i = 0; i < info.nc; i++) {
int h, v;
comps[i].cid = getbyte();
comps[i].hv = getbyte();
v = comps[i].hv & 15;
h = comps[i].hv >> 4;
comps[i].tq = getbyte();
if (h > 3 || v > 3)
return ERR_ILLEGAL_HV;
if (comps[i].tq > 3)
return ERR_QUANT_TABLE_SELECTOR;
}
if (readtables(M_SOS))
return ERR_BAD_TABLES;
getword();
info.ns = getbyte();
if (info.ns != 3)
return ERR_NOT_YCBCR_221111;
for (i = 0; i < 3; i++) {
dscans[i].cid = getbyte();
tdc = getbyte();
tac = tdc & 15;
tdc >>= 4;
if (tdc > 1 || tac > 1)
return ERR_QUANT_TABLE_SELECTOR;
for (j = 0; j < info.nc; j++)
if (comps[j].cid == dscans[i].cid)
break;
if (j == info.nc)
return ERR_UNKNOWN_CID_IN_SCAN;
dscans[i].hv = comps[j].hv;
dscans[i].tq = comps[j].tq;
dscans[i].hudc.dhuff = dec_huffdc + tdc;
dscans[i].huac.dhuff = dec_huffac + tac;
}
i = getbyte();
j = getbyte();
m = getbyte();
if (i != 0 || j != 63 || m != 0)
return ERR_NOT_SEQUENTIAL_DCT;
if (dscans[0].cid != 1 || dscans[1].cid != 2 || dscans[2].cid != 3)
return ERR_NOT_YCBCR_221111;
if (dscans[0].hv != 0x22 || dscans[1].hv != 0x11 || dscans[2].hv != 0x11)
return ERR_NOT_YCBCR_221111;
mcusx = width >> 4;
mcusy = height >> 4;
idctqtab(quant[dscans[0].tq], decdata->dquant[0]);
idctqtab(quant[dscans[1].tq], decdata->dquant[1]);
idctqtab(quant[dscans[2].tq], decdata->dquant[2]);
initcol(decdata->dquant);
setinput(&in, datap);
#if 0
/* landing zone */
img[len] = 0;
img[len + 1] = 0xff;
img[len + 2] = M_EOF;
#endif
dec_initscans();
dscans[0].next = 6 - 4;
dscans[1].next = 6 - 4 - 1;
dscans[2].next = 6 - 4 - 1 - 1; /* 411 encoding */
for (my = 0; my < mcusy; my++) {
for (mx = 0; mx < mcusx; mx++) {
if (info.dri && !--info.nm)
if (dec_checkmarker())
return ERR_WRONG_MARKER;
decode_mcus(&in, decdata->dcts, 6, dscans, max);
idct(decdata->dcts, decdata->out, decdata->dquant[0], IFIX(128.5), max[0]);
idct(decdata->dcts + 64, decdata->out + 64, decdata->dquant[0], IFIX(128.5), max[1]);
idct(decdata->dcts + 128, decdata->out + 128, decdata->dquant[0], IFIX(128.5), max[2]);
idct(decdata->dcts + 192, decdata->out + 192, decdata->dquant[0], IFIX(128.5), max[3]);
idct(decdata->dcts + 256, decdata->out + 256, decdata->dquant[1], IFIX(0.5), max[4]);
idct(decdata->dcts + 320, decdata->out + 320, decdata->dquant[2], IFIX(0.5), max[5]);
switch (depth) {
case 32:
col221111_32(decdata->out, pic + (my * 16 * mcusx + mx) * 16 * 4, mcusx * 16 * 4);
break;
case 24:
col221111(decdata->out, pic + (my * 16 * mcusx + mx) * 16 * 3, mcusx * 16 * 3);
break;
case 16:
col221111_16(decdata->out, pic + (my * 16 * mcusx + mx) * (16 * 2), mcusx * (16 * 2));
break;
default:
return ERR_DEPTH_MISMATCH;
break;
}
}
}
m = dec_readmarker(&in);
if (m != M_EOI)
return ERR_NO_EOI;
return 0;
}
/****************************************************************/
/************** huffman decoder ***************/
/****************************************************************/
static int fillbits __P((struct in *, int, unsigned int));
static int dec_rec2
__P((struct in *, struct dec_hufftbl *, int *, int, int));
static void setinput(struct in *in, unsigned char *p)
{
in->p = p;
in->left = 0;
in->bits = 0;
in->marker = 0;
}
static int fillbits(struct in *in, int le, unsigned int bi)
{
int b, m;
if (in->marker) {
if (le <= 16)
in->bits = bi << 16, le += 16;
return le;
}
while (le <= 24) {
b = *in->p++;
if (b == 0xff && (m = *in->p++) != 0) {
if (m == M_EOF) {
if (in->func && (m = in->func(in->data)) == 0)
continue;
}
in->marker = m;
if (le <= 16)
bi = bi << 16, le += 16;
break;
}
bi = bi << 8 | b;
le += 8;
}
in->bits = bi; /* tmp... 2 return values needed */
return le;
}
static int dec_readmarker(struct in *in)
{
int m;
in->left = fillbits(in, in->left, in->bits);
if ((m = in->marker) == 0)
return 0;
in->left = 0;
in->marker = 0;
return m;
}
#define LEBI_DCL int le, bi
#define LEBI_GET(in) (le = in->left, bi = in->bits)
#define LEBI_PUT(in) (in->left = le, in->bits = bi)
#define GETBITS(in, n) ( \
(le < (n) ? le = fillbits(in, le, bi), bi = in->bits : 0), \
(le -= (n)), \
bi >> le & ((1 << (n)) - 1) \
)
#define UNGETBITS(in, n) ( \
le += (n) \
)
static int dec_rec2(struct in *in, struct dec_hufftbl *hu, int *runp, int c,
int i)
{
LEBI_DCL;
LEBI_GET(in);
if (i) {
UNGETBITS(in, i & 127);
*runp = i >> 8 & 15;
i >>= 16;
} else {
for (i = DECBITS; (c = ((c << 1) | GETBITS(in, 1))) >= (hu->maxcode[i]); i++);
if (i >= 16) {
in->marker = M_BADHUFF;
return 0;
}
i = hu->vals[hu->valptr[i] + c - hu->maxcode[i - 1] * 2];
*runp = i >> 4;
i &= 15;
}
if (i == 0) { /* sigh, 0xf0 is 11 bit */
LEBI_PUT(in);
return 0;
}
/* receive part */
c = GETBITS(in, i);
if (c < (1 << (i - 1)))
c += (-1 << i) + 1;
LEBI_PUT(in);
return c;
}
#define DEC_REC(in, hu, r, i) ( \
r = GETBITS(in, DECBITS), \
i = hu->llvals[r], \
i & 128 ? \
( \
UNGETBITS(in, i & 127), \
r = i >> 8 & 15, \
i >> 16 \
) \
: \
( \
LEBI_PUT(in), \
i = dec_rec2(in, hu, &r, r, i), \
LEBI_GET(in), \
i \
) \
)
static void decode_mcus(struct in *in, int *dct, int n, struct scan *sc, int *maxp)
{
struct dec_hufftbl *hu;
int i, r, t;
LEBI_DCL;
memset(dct, 0, n * 64 * sizeof(*dct));
LEBI_GET(in);
while (n-- > 0) {
hu = sc->hudc.dhuff;
*dct++ = (sc->dc += DEC_REC(in, hu, r, t));
hu = sc->huac.dhuff;
i = 63;
while (i > 0) {
t = DEC_REC(in, hu, r, t);
if (t == 0 && r == 0) {
dct += i;
break;
}
dct += r;
*dct++ = t;
i -= r + 1;
}
*maxp++ = 64 - i;
if (n == sc->next)
sc++;
}
LEBI_PUT(in);
}
static void dec_makehuff(struct dec_hufftbl *hu, int *hufflen, unsigned char *huffvals)
{
int code, k, i, j, d, x, c, v;
for (i = 0; i < (1 << DECBITS); i++)
hu->llvals[i] = 0;
/*
* llvals layout:
*
* value v already known, run r, backup u bits:
* vvvvvvvvvvvvvvvv 0000 rrrr 1 uuuuuuu
* value unknown, size b bits, run r, backup u bits:
* 000000000000bbbb 0000 rrrr 0 uuuuuuu
* value and size unknown:
* 0000000000000000 0000 0000 0 0000000
*/
code = 0;
k = 0;
for (i = 0; i < 16; i++, code <<= 1) { /* sizes */
hu->valptr[i] = k;
for (j = 0; j < hufflen[i]; j++) {
hu->vals[k] = *huffvals++;
if (i < DECBITS) {
c = code << (DECBITS - 1 - i);
v = hu->vals[k] & 0x0f; /* size */
for (d = 1 << (DECBITS - 1 - i); --d >= 0;) {
if (v + i < DECBITS) { /* both fit in table */
x = d >> (DECBITS - 1 - v -
i);
if (v && x < (1 << (v - 1)))
x += (-1 << v) + 1;
x = x << 16 | (hu-> vals[k] & 0xf0) << 4 |
(DECBITS - (i + 1 + v)) | 128;
} else
x = v << 16 | (hu-> vals[k] & 0xf0) << 4 |
(DECBITS - (i + 1));
hu->llvals[c | d] = x;
}
}
code++;
k++;
}
hu->maxcode[i] = code;
}
hu->maxcode[16] = 0x20000; /* always terminate decode */
}
/****************************************************************/
/************** idct ***************/
/****************************************************************/
#define ONE ((PREC)IFIX(1.))
#define S2 ((PREC)IFIX(0.382683432))
#define C2 ((PREC)IFIX(0.923879532))
#define C4 ((PREC)IFIX(0.707106781))
#define S22 ((PREC)IFIX(2 * 0.382683432))
#define C22 ((PREC)IFIX(2 * 0.923879532))
#define IC4 ((PREC)IFIX(1 / 0.707106781))
#define C3IC1 ((PREC)IFIX(0.847759065)) /* c3/c1 */
#define C5IC1 ((PREC)IFIX(0.566454497)) /* c5/c1 */
#define C7IC1 ((PREC)IFIX(0.198912367)) /* c7/c1 */
#define XPP(a,b) (t = a + b, b = a - b, a = t)
#define XMP(a,b) (t = a - b, b = a + b, a = t)
#define XPM(a,b) (t = a + b, b = b - a, a = t)
#define ROT(a,b,s,c) ( t = IMULT(a + b, s), \
a = IMULT(a, c - s) + t, \
b = IMULT(b, c + s) - t)
#define IDCT \
( \
XPP(t0, t1), \
XMP(t2, t3), \
t2 = IMULT(t2, IC4) - t3, \
XPP(t0, t3), \
XPP(t1, t2), \
XMP(t4, t7), \
XPP(t5, t6), \
XMP(t5, t7), \
t5 = IMULT(t5, IC4), \
ROT(t4, t6, S22, C22),\
t6 -= t7, \
t5 -= t6, \
t4 -= t5, \
XPP(t0, t7), \
XPP(t1, t6), \
XPP(t2, t5), \
XPP(t3, t4) \
)
static unsigned char zig2[64] = {
0, 2, 3, 9, 10, 20, 21, 35,
14, 16, 25, 31, 39, 46, 50, 57,
5, 7, 12, 18, 23, 33, 37, 48,
27, 29, 41, 44, 52, 55, 59, 62,
15, 26, 30, 40, 45, 51, 56, 58,
1, 4, 8, 11, 19, 22, 34, 36,
28, 42, 43, 53, 54, 60, 61, 63,
6, 13, 17, 24, 32, 38, 47, 49
};
void idct(int *in, int *out, PREC *quant, PREC off, int max)
{
PREC t0, t1, t2, t3, t4, t5, t6, t7, t;
PREC tmp[64], *tmpp;
int i, j;
unsigned char *zig2p;
t0 = off;
if (max == 1) {
t0 += in[0] * quant[0];
for (i = 0; i < 64; i++)
out[i] = ITOINT(t0);
return;
}
zig2p = zig2;
tmpp = tmp;
for (i = 0; i < 8; i++) {
j = *zig2p++;
t0 += in[j] * quant[j];
j = *zig2p++;
t5 = in[j] * quant[j];
j = *zig2p++;
t2 = in[j] * quant[j];
j = *zig2p++;
t7 = in[j] * quant[j];
j = *zig2p++;
t1 = in[j] * quant[j];
j = *zig2p++;
t4 = in[j] * quant[j];
j = *zig2p++;
t3 = in[j] * quant[j];
j = *zig2p++;
t6 = in[j] * quant[j];
IDCT;
tmpp[0 * 8] = t0;
tmpp[1 * 8] = t1;
tmpp[2 * 8] = t2;
tmpp[3 * 8] = t3;
tmpp[4 * 8] = t4;
tmpp[5 * 8] = t5;
tmpp[6 * 8] = t6;
tmpp[7 * 8] = t7;
tmpp++;
t0 = 0;
}
for (i = 0; i < 8; i++) {
t0 = tmp[8 * i + 0];
t1 = tmp[8 * i + 1];
t2 = tmp[8 * i + 2];
t3 = tmp[8 * i + 3];
t4 = tmp[8 * i + 4];
t5 = tmp[8 * i + 5];
t6 = tmp[8 * i + 6];
t7 = tmp[8 * i + 7];
IDCT;
out[8 * i + 0] = ITOINT(t0);
out[8 * i + 1] = ITOINT(t1);
out[8 * i + 2] = ITOINT(t2);
out[8 * i + 3] = ITOINT(t3);
out[8 * i + 4] = ITOINT(t4);
out[8 * i + 5] = ITOINT(t5);
out[8 * i + 6] = ITOINT(t6);
out[8 * i + 7] = ITOINT(t7);
}
}
static unsigned char zig[64] = {
0, 1, 5, 6, 14, 15, 27, 28,
2, 4, 7, 13, 16, 26, 29, 42,
3, 8, 12, 17, 25, 30, 41, 43,
9, 11, 18, 24, 31, 40, 44, 53,
10, 19, 23, 32, 39, 45, 52, 54,
20, 22, 33, 38, 46, 51, 55, 60,
21, 34, 37, 47, 50, 56, 59, 61,
35, 36, 48, 49, 57, 58, 62, 63
};
static PREC aaidct[8] = {
IFIX(0.3535533906), IFIX(0.4903926402),
IFIX(0.4619397663), IFIX(0.4157348062),
IFIX(0.3535533906), IFIX(0.2777851165),
IFIX(0.1913417162), IFIX(0.0975451610)
};
static void idctqtab(unsigned char *qin, PREC *qout)
{
int i, j;
for (i = 0; i < 8; i++)
for (j = 0; j < 8; j++)
qout[zig[i * 8 + j]] = qin[zig[i * 8 + j]] *
IMULT(aaidct[i], aaidct[j]);
}
static void scaleidctqtab(PREC *q, PREC sc)
{
int i;
for (i = 0; i < 64; i++)
q[i] = IMULT(q[i], sc);
}
/****************************************************************/
/************** color decoder ***************/
/****************************************************************/
#define ROUND
/*
* YCbCr Color transformation:
*
* y:0..255 Cb:-128..127 Cr:-128..127
*
* R = Y + 1.40200 * Cr
* G = Y - 0.34414 * Cb - 0.71414 * Cr
* B = Y + 1.77200 * Cb
*
* =>
* Cr *= 1.40200;
* Cb *= 1.77200;
* Cg = 0.19421 * Cb + .50937 * Cr;
* R = Y + Cr;
* G = Y - Cg;
* B = Y + Cb;
*
* =>
* Cg = (50 * Cb + 130 * Cr + 128) >> 8;
*/
static void initcol(PREC q[][64])
{
scaleidctqtab(q[1], IFIX(1.77200));
scaleidctqtab(q[2], IFIX(1.40200));
}
/* This is optimized for the stupid sun SUNWspro compiler. */
#define STORECLAMP(a,x) \
( \
(a) = (x), \
(unsigned int)(x) >= 256 ? \
((a) = (x) < 0 ? 0 : 255) \
: \
0 \
)
#define CLAMP(x) ((unsigned int)(x) >= 256 ? ((x) < 0 ? 0 : 255) : (x))
#ifdef ROUND
#define CBCRCG(yin, xin) \
( \
cb = outc[0 +yin*8+xin], \
cr = outc[64+yin*8+xin], \
cg = (50 * cb + 130 * cr + 128) >> 8 \
)
#else
#define CBCRCG(yin, xin) \
( \
cb = outc[0 +yin*8+xin], \
cr = outc[64+yin*8+xin], \
cg = (3 * cb + 8 * cr) >> 4 \
)
#endif
#define PIC(yin, xin, p, xout) \
( \
y = outy[(yin) * 8 + xin], \
STORECLAMP(p[(xout) * 3 + 0], y + cr), \
STORECLAMP(p[(xout) * 3 + 1], y - cg), \
STORECLAMP(p[(xout) * 3 + 2], y + cb) \
)
#ifdef __LITTLE_ENDIAN
#define PIC_16(yin, xin, p, xout, add) \
( \
y = outy[(yin) * 8 + xin], \
y = ((CLAMP(y + cr + add*2+1) & 0xf8) << 8) | \
((CLAMP(y - cg + add ) & 0xfc) << 3) | \
((CLAMP(y + cb + add*2+1) ) >> 3), \
p[(xout) * 2 + 0] = y & 0xff, \
p[(xout) * 2 + 1] = y >> 8 \
)
#else
#ifdef CONFIG_PPC
#define PIC_16(yin, xin, p, xout, add) \
( \
y = outy[(yin) * 8 + xin], \
y = ((CLAMP(y + cr + add*2+1) & 0xf8) << 7) | \
((CLAMP(y - cg + add*2+1) & 0xf8) << 2) | \
((CLAMP(y + cb + add*2+1) ) >> 3), \
p[(xout) * 2 + 0] = y >> 8, \
p[(xout) * 2 + 1] = y & 0xff \
)
#else
#define PIC_16(yin, xin, p, xout, add) \
( \
y = outy[(yin) * 8 + xin], \
y = ((CLAMP(y + cr + add*2+1) & 0xf8) << 8) | \
((CLAMP(y - cg + add ) & 0xfc) << 3) | \
((CLAMP(y + cb + add*2+1) ) >> 3), \
p[(xout) * 2 + 0] = y >> 8, \
p[(xout) * 2 + 1] = y & 0xff \
)
#endif
#endif
#define PIC_32(yin, xin, p, xout) \
( \
y = outy[(yin) * 8 + xin], \
STORECLAMP(p[(xout) * 4 + 0], y + cr), \
STORECLAMP(p[(xout) * 4 + 1], y - cg), \
STORECLAMP(p[(xout) * 4 + 2], y + cb), \
p[(xout) * 4 + 3] = 0 \
)
#define PIC221111(xin) \
( \
CBCRCG(0, xin), \
PIC(xin / 4 * 8 + 0, (xin & 3) * 2 + 0, pic0, xin * 2 + 0), \
PIC(xin / 4 * 8 + 0, (xin & 3) * 2 + 1, pic0, xin * 2 + 1), \
PIC(xin / 4 * 8 + 1, (xin & 3) * 2 + 0, pic1, xin * 2 + 0), \
PIC(xin / 4 * 8 + 1, (xin & 3) * 2 + 1, pic1, xin * 2 + 1) \
)
#define PIC221111_16(xin) \
( \
CBCRCG(0, xin), \
PIC_16(xin / 4 * 8 + 0, (xin & 3) * 2 + 0, pic0, xin * 2 + 0, 3), \
PIC_16(xin / 4 * 8 + 0, (xin & 3) * 2 + 1, pic0, xin * 2 + 1, 0), \
PIC_16(xin / 4 * 8 + 1, (xin & 3) * 2 + 0, pic1, xin * 2 + 0, 1), \
PIC_16(xin / 4 * 8 + 1, (xin & 3) * 2 + 1, pic1, xin * 2 + 1, 2) \
)
#define PIC221111_32(xin) \
( \
CBCRCG(0, xin), \
PIC_32(xin / 4 * 8 + 0, (xin & 3) * 2 + 0, pic0, xin * 2 + 0),\
PIC_32(xin / 4 * 8 + 0, (xin & 3) * 2 + 1, pic0, xin * 2 + 1),\
PIC_32(xin / 4 * 8 + 1, (xin & 3) * 2 + 0, pic1, xin * 2 + 0),\
PIC_32(xin / 4 * 8 + 1, (xin & 3) * 2 + 1, pic1, xin * 2 + 1) \
)
static void col221111(int *out, unsigned char *pic, int width)
{
int i, j, k;
unsigned char *pic0, *pic1;
int *outy, *outc;
int cr, cg, cb, y;
pic0 = pic;
pic1 = pic + width;
outy = out;
outc = out + 64 * 4;
for (i = 2; i > 0; i--) {
for (j = 4; j > 0; j--) {
for (k = 0; k < 8; k++) {
PIC221111(k);
}
outc += 8;
outy += 16;
pic0 += 2 * width;
pic1 += 2 * width;
}
outy += 64 * 2 - 16 * 4;
}
}
static void col221111_16(int *out, unsigned char *pic, int width)
{
int i, j, k;
unsigned char *pic0, *pic1;
int *outy, *outc;
int cr, cg, cb, y;
pic0 = pic;
pic1 = pic + width;
outy = out;
outc = out + 64 * 4;
for (i = 2; i > 0; i--) {
for (j = 4; j > 0; j--) {
for (k = 0; k < 8; k++) {
PIC221111_16(k);
}
outc += 8;
outy += 16;
pic0 += 2 * width;
pic1 += 2 * width;
}
outy += 64 * 2 - 16 * 4;
}
}
static void col221111_32(int *out, unsigned char *pic, int width)
{
int i, j, k;
unsigned char *pic0, *pic1;
int *outy, *outc;
int cr, cg, cb, y;
pic0 = pic;
pic1 = pic + width;
outy = out;
outc = out + 64 * 4;
for (i = 2; i > 0; i--) {
for (j = 4; j > 0; j--) {
for (k = 0; k < 8; k++) {
PIC221111_32(k);
}
outc += 8;
outy += 16;
pic0 += 2 * width;
pic1 += 2 * width;
}
outy += 64 * 2 - 16 * 4;
}
}

56
src/lib/jpeg.h Normal file
View File

@ -0,0 +1,56 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2001 by Michael Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
/*
* a tiny jpeg decoder.
*
* written in August 2001 by Michael Schroeder <mls@suse.de>
*/
#ifndef __JPEG_H
#define __JPEG_H
#define ERR_NO_SOI 1
#define ERR_NOT_8BIT 2
#define ERR_HEIGHT_MISMATCH 3
#define ERR_WIDTH_MISMATCH 4
#define ERR_BAD_WIDTH_OR_HEIGHT 5
#define ERR_TOO_MANY_COMPPS 6
#define ERR_ILLEGAL_HV 7
#define ERR_QUANT_TABLE_SELECTOR 8
#define ERR_NOT_YCBCR_221111 9
#define ERR_UNKNOWN_CID_IN_SCAN 10
#define ERR_NOT_SEQUENTIAL_DCT 11
#define ERR_WRONG_MARKER 12
#define ERR_NO_EOI 13
#define ERR_BAD_TABLES 14
#define ERR_DEPTH_MISMATCH 15
struct jpeg_decdata {
int dcts[6 * 64 + 16];
int out[64 * 6];
int dquant[3][64];
};
int jpeg_decode(unsigned char *, unsigned char *, int, int, int, struct jpeg_decdata *);
int jpeg_check_size(unsigned char *, int, int);
#endif