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

View File

@ -1,72 +0,0 @@
##
## This file is part of the coreboot project.
##
## Copyright (C) 2007 coresystems GmbH
##
## 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; either version 2 of the License, or
## (at your option) any later version.
##
## 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
##
#X86EMU_INCLUDE = -I $(src)/util/x86emu/include
X86EMU_SRC = debug.c decode.c fpu.c ops.c ops2.c prim_ops.c sys.c
ifeq ($(CONFIG_PCI_OPTION_ROM_RUN_X86EMU),y)
BIOSEMU_SRC = biosemu.c
endif
ifeq ($(CONFIG_PCI_OPTION_ROM_RUN_YABEL),y)
BIOSEMU_SRC = biosemu.c debug.c device.c mem.c io.c interrupt.c
#TODO: add vbe.c, currently not needed...
#BIOSEMU_SRC +=vbe.c
BIOSEMU_SRC +=pmm.c
#PH: TODO: remove the compat files??
BIOSEMU_SRC += compat/functions.c
X86EMU_INCLUDE += -I $(src)/util/x86emu/yabel
X86EMU_INCLUDE += -I $(src)/util/x86emu
#TODO: remove these, these are .h files from slof, to make the merge easier...
X86EMU_INCLUDE += -I $(src)/util/x86emu/yabel/compat
endif
REALMODE_SRC = x86.c x86_asm.S
ifeq ($(CONFIG_PCI_OPTION_ROM_RUN_X86EMU),y)
LIBX86EMU_SRC=$(patsubst %,x86emu/%,$(X86EMU_SRC)) $(BIOSEMU_SRC)
endif
ifeq ($(CONFIG_PCI_OPTION_ROM_RUN_YABEL),y)
LIBX86EMU_SRC=$(patsubst %,x86emu/%,$(X86EMU_SRC)) $(patsubst %,yabel/%,$(BIOSEMU_SRC))
endif
ifeq ($(CONFIG_PCI_OPTION_ROM_RUN_REALMODE),y)
LIBX86EMU_SRC=$(REALMODE_SRC)
endif
LIBX86EMU_OBJS = $(patsubst %.c,$(obj)/util/x86emu/%.o,$(LIBX86EMU_SRC))
# needed for kscope
PCIROM_SRC += $(patsubst %,$(src)/util/x86emu/%,$(LIBX86EMU_SRC))
$(obj)/util/x86emu/libx86emu.a: $(LIBX86EMU_OBJS) $(src)/.config
@printf " AR $(subst $(shell pwd)/,,$(@))\n"
$(Q)rm -f $@ # otherwise we always add to the archive
$(Q)$(AR) qcs $@ $(LIBX86EMU_OBJS)
#
# This rule is also valid for all subdirectories
#
$(obj)/util/x86emu/%.o: $(src)/util/x86emu/%.c
@printf " CC $(subst $(shell pwd)/,,$(@))\n"
$(Q)mkdir -p $(dir $@)
$(Q)$(CC) -Werror $(INITCFLAGS) $(X86EMU_INCLUDE) -I$(src)/util/x86emu/include -c $< -o $@

View File

@ -1,12 +1,11 @@
##
## This file is part of the coreboot project.
##
## Copyright (C) 2007 coresystems GmbH
## Copyright (C) 2007-2010 coresystems GmbH
##
## 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; either version 2 of the License, or
## (at your option) any later version.
## 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
@ -18,9 +17,6 @@
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
##
subdirs-$(CONFIG_PCI_OPTION_ROM_RUN_X86EMU) += x86emu
obj-$(CONFIG_PCI_OPTION_ROM_RUN_X86EMU) += biosemu.o
obj-$(CONFIG_PCI_OPTION_ROM_RUN_REALMODE) += x86.o
obj-$(CONFIG_PCI_OPTION_ROM_RUN_REALMODE) += x86_asm.o
obj-$(CONFIG_PCI_OPTION_ROM_RUN_REALMODE) += x86_interrupts.o

View File

@ -1,580 +0,0 @@
/*
* This software and ancillary information (herein called SOFTWARE )
* called LinuxBIOS is made available under the terms described
* here. The SOFTWARE has been approved for release with associated
* LA-CC Number 00-34 . Unless otherwise indicated, this SOFTWARE has
* been authored by an employee or employees of the University of
* California, operator of the Los Alamos National Laboratory under
* Contract No. W-7405-ENG-36 with the U.S. Department of Energy. The
* U.S. Government has rights to use, reproduce, and distribute this
* SOFTWARE. The public may copy, distribute, prepare derivative works
* and publicly display this SOFTWARE without charge, provided that this
* Notice and any statement of authorship are reproduced on all copies.
* Neither the Government nor the University makes any warranty, express
* or implied, or assumes any liability or responsibility for the use of
* this SOFTWARE. If SOFTWARE is modified to produce derivative works,
* such modified SOFTWARE should be clearly marked, so as not to confuse
* it with the version available from LANL.
*/
/*
* This file is part of the coreboot project.
*
* (c) Copyright 2000, Ron Minnich, Advanced Computing Lab, LANL
* Copyright (C) 2009 coresystems GmbH
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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
*/
#include <string.h>
#include <arch/io.h>
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <x86emu/x86emu.h>
#include "x86emu/prim_ops.h"
#define DATA_SEGMENT 0x2000
#define STACK_SEGMENT 0x1000 //1000:xxxx
#define STACK_START_OFFSET 0xfffe
#define INITIAL_EBDA_SEGMENT 0xF600 // segment of the Extended BIOS Data Area
#define INITIAL_EBDA_SIZE 0x400 // size of the EBDA (at least 1KB!! since size is stored in KB!)
enum {
PCI_BIOS_PRESENT = 0xB101,
FIND_PCI_DEVICE = 0xB102,
FIND_PCI_CLASS_CODE = 0xB103,
GENERATE_SPECIAL_CYCLE = 0xB106,
READ_CONFIG_BYTE = 0xB108,
READ_CONFIG_WORD = 0xB109,
READ_CONFIG_DWORD = 0xB10A,
WRITE_CONFIG_BYTE = 0xB10B,
WRITE_CONFIG_WORD = 0xB10C,
WRITE_CONFIG_DWORD = 0xB10D,
GET_IRQ_ROUTING_OPTIONS = 0xB10E,
SET_PCI_IRQ = 0xB10F
};
enum {
SUCCESSFUL = 0x00,
FUNC_NOT_SUPPORTED = 0x81,
BAD_VENDOR_ID = 0x83,
DEVICE_NOT_FOUND = 0x86,
BAD_REGISTER_NUMBER = 0x87,
SET_FAILED = 0x88,
BUFFER_TOO_SMALL = 0x89
};
#define MEM_WB(where, what) wrb(where, what)
#define MEM_WW(where, what) wrw(where, what)
#define MEM_WL(where, what) wrl(where, what)
#define MEM_RB(where) rdb(where)
#define MEM_RW(where) rdw(where)
#define MEM_RL(where) rdl(where)
static u8 biosemu_inb(u16 port)
{
u8 val;
val = inb(port);
#ifdef DEBUG
if (port != 0x40)
printk("inb(0x%04x) = 0x%02x\n", port, val);
#endif
return val;
}
static u16 biosemu_inw(u16 port)
{
u16 val;
val = inw(port);
#ifdef DEBUG
printk("inw(0x%04x) = 0x%04x\n", port, val);
#endif
return val;
}
static u32 biosemu_inl(u16 port)
{
u32 val;
val = inl(port);
#ifdef DEBUG
printk("inl(0x%04x) = 0x%08x\n", port, val);
#endif
return val;
}
static void biosemu_outb(u16 port, u8 val)
{
#ifdef DEBUG
if (port != 0x43)
printk("outb(0x%02x, 0x%04x)\n", val, port);
#endif
outb(val, port);
}
static void biosemu_outw(u16 port, u16 val)
{
#ifdef DEBUG
printk("outw(0x%04x, 0x%04x)\n", val, port);
#endif
outw(val, port);
}
static void biosemu_outl(u16 port, u32 val)
{
#ifdef DEBUG
printk("outl(0x%08x, 0x%04x)\n", val, port);
#endif
outl(val, port);
}
static X86EMU_pioFuncs biosemu_piofuncs = {
biosemu_inb, biosemu_inw, biosemu_inl,
biosemu_outb, biosemu_outw, biosemu_outl
};
/* Interrupt Handlers */
static int int15_handler(void)
{
/* This int15 handler is VIA Tech. and Intel specific. Other chipsets need other
* handlers. The right way to do this is to move this handler code into
* the mainboard or northbridge code.
*/
switch (X86_AX) {
case 0x5f19:
X86_EFLAGS |= FB_CF; /* set carry flag */
break;
case 0x5f18:
X86_EAX = 0x5f;
// MCLK = 133, 32M frame buffer, 256 M main memory
X86_EBX = 0x545;
X86_ECX = 0x060;
X86_EFLAGS &= ~FB_CF;
break;
case 0x5f00:
X86_EAX = 0x8600;
X86_EFLAGS |= FB_CF; /* set carry flag */
break;
case 0x5f01:
X86_EAX = 0x5f;
X86_ECX = (X86_ECX & 0xffffff00 ) | 2; // panel type = 2 = 1024 * 768
X86_EFLAGS &= ~FB_CF;
break;
case 0x5f02:
X86_EAX = 0x5f;
X86_EBX = (X86_EBX & 0xffff0000) | 2;
X86_ECX = (X86_ECX & 0xffff0000) | 0x401; // PAL + crt only
X86_EDX = (X86_EDX & 0xffff0000) | 0; // TV Layout - default
X86_EFLAGS &= ~FB_CF;
break;
case 0x5f0f:
X86_EAX = 0x860f;
X86_EFLAGS |= FB_CF; /* set carry flag */
break;
/* And now Intel IGD code */
#define BOOT_DISPLAY_DEFAULT 0
#define BOOT_DISPLAY_CRT (1 << 0)
#define BOOT_DISPLAY_TV (1 << 1)
#define BOOT_DISPLAY_EFP (1 << 2)
#define BOOT_DISPLAY_LCD (1 << 3)
#define BOOT_DISPLAY_CRT2 (1 << 4)
#define BOOT_DISPLAY_TV2 (1 << 5)
#define BOOT_DISPLAY_EFP2 (1 << 6)
#define BOOT_DISPLAY_LCD2 (1 << 7)
case 0x5f35:
X86_EAX = 0x5f;
X86_ECX = BOOT_DISPLAY_DEFAULT;
X86_EFLAGS &= ~FB_CF;
break;
case 0x5f40:
X86_EAX = 0x5f;
X86_ECX = 3; // This is mainboard specific
printk("DISPLAY=%x\n", X86_ECX);
X86_EFLAGS &= ~FB_CF;
break;
default:
printk("Unknown INT15 function %04x!\n", X86_AX);
X86_EFLAGS |= FB_CF; /* set carry flag */
}
return 1;
}
static int int1a_handler(void)
{
int ret = 0;
struct device *dev = 0;
switch (X86_AX) {
case PCI_BIOS_PRESENT:
X86_AH = 0x00; /* no config space/special cycle support */
X86_AL = 0x01; /* config mechanism 1 */
X86_EDX = 'P' | 'C' << 8 | 'I' << 16 | ' ' << 24;
X86_EBX = 0x0210; /* Version 2.10 */
X86_ECX = 0xFF00; /* FIXME: Max bus number */
X86_EFLAGS &= ~FB_CF; /* clear carry flag */
ret = 1;
break;
case FIND_PCI_DEVICE:
/* FIXME: support SI != 0 */
dev = dev_find_device(X86_DX, X86_CX, dev);
if (dev != 0) {
X86_BH = dev->bus->secondary;
X86_BL = dev->path.pci.devfn;
X86_AH = SUCCESSFUL;
X86_EFLAGS &= ~FB_CF; /* clear carry flag */
ret = 1;
} else {
X86_AH = DEVICE_NOT_FOUND;
X86_EFLAGS |= FB_CF; /* set carry flag */
ret = 0;
}
break;
case FIND_PCI_CLASS_CODE:
/* FixME: support SI != 0 */
dev = dev_find_class(X86_ECX, dev);
if (dev != 0) {
X86_BH = dev->bus->secondary;
X86_BL = dev->path.pci.devfn;
X86_AH = SUCCESSFUL;
X86_EFLAGS &= ~FB_CF; /* clear carry flag */
ret = 1;
} else {
X86_AH = DEVICE_NOT_FOUND;
X86_EFLAGS |= FB_CF; /* set carry flag */
ret = 0;
}
break;
case READ_CONFIG_BYTE:
dev = dev_find_slot(X86_BH, X86_BL);
if (dev != 0) {
X86_CL = pci_read_config8(dev, X86_DI);
X86_AH = SUCCESSFUL;
X86_EFLAGS &= ~FB_CF; /* clear carry flag */
ret = 1;
} else {
X86_AH = DEVICE_NOT_FOUND;
X86_EFLAGS |= FB_CF; /* set carry flag */
ret = 0;
}
break;
case READ_CONFIG_WORD:
dev = dev_find_slot(X86_BH, X86_BL);
if (dev != 0) {
X86_CX = pci_read_config16(dev, X86_DI);
X86_AH = SUCCESSFUL;
X86_EFLAGS &= ~FB_CF; /* clear carry flag */
ret = 1;
} else {
X86_AH = DEVICE_NOT_FOUND;
X86_EFLAGS |= FB_CF; /* set carry flag */
ret = 0;
}
break;
case READ_CONFIG_DWORD:
dev = dev_find_slot(X86_BH, X86_BL);
if (dev != 0) {
X86_ECX = pci_read_config32(dev, X86_DI);
X86_AH = SUCCESSFUL;
X86_EFLAGS &= ~FB_CF; /* clear carry flag */
ret = 1;
} else {
X86_AH = DEVICE_NOT_FOUND;
X86_EFLAGS |= FB_CF; /* set carry flag */
ret = 0;
}
break;
case WRITE_CONFIG_BYTE:
dev = dev_find_slot(X86_BH, X86_BL);
if (dev != 0) {
pci_write_config8(dev, X86_DI, X86_CL);
X86_AH = SUCCESSFUL;
X86_EFLAGS &= ~FB_CF; /* clear carry flag */
ret = 1;
} else {
X86_AH = DEVICE_NOT_FOUND;
X86_EFLAGS |= FB_CF; /* set carry flag */
ret = 0;
}
break;
case WRITE_CONFIG_WORD:
dev = dev_find_slot(X86_BH, X86_BL);
if (dev != 0) {
pci_write_config16(dev, X86_DI, X86_CX);
X86_AH = SUCCESSFUL;
X86_EFLAGS &= ~FB_CF; /* clear carry flag */
ret = 1;
} else {
X86_AH = DEVICE_NOT_FOUND;
X86_EFLAGS |= FB_CF; /* set carry flag */
ret = 0;
}
break;
case WRITE_CONFIG_DWORD:
dev = dev_find_slot(X86_BH, X86_BL);
if (dev != 0) {
pci_write_config16(dev, X86_DI, X86_ECX);
X86_AH = SUCCESSFUL;
X86_EFLAGS &= ~FB_CF; /* clear carry flag */
ret = 1;
} else {
X86_AH = DEVICE_NOT_FOUND;
X86_EFLAGS |= FB_CF; /* set carry flag */
ret = 0;
}
break;
default:
X86_AH = FUNC_NOT_SUPPORTED;
X86_EFLAGS |= FB_CF;
break;
}
return ret;
}
/* Interrupt multiplexer */
/* Find base address of interrupt handler */
static u32 getIntVect(int num)
{
return MEM_RW(num << 2) + (MEM_RW((num << 2) + 2) << 4);
}
static int run_bios_int(int num)
{
u32 eflags;
eflags = X86_EFLAGS;
push_word(eflags);
push_word(X86_CS);
push_word(X86_IP);
X86_CS = MEM_RW((num << 2) + 2);
X86_IP = MEM_RW(num << 2);
return 1;
}
static void do_int(int num)
{
int ret = 0;
printk("int%x (AX=%04x) vector at %x\n", num, X86_AX, getIntVect(num));
switch (num) {
case 0x10:
case 0x42:
case 0x6D:
if (getIntVect(num) == 0x0000) {
printk("uninitialized interrupt vector\n");
ret = 1;
}
if (getIntVect(num) == 0xFF065) {
//ret = int42_handler();
ret = 1;
}
break;
case 0x15:
ret = int15_handler();
ret = 1;
break;
case 0x16:
//ret = int16_handler();
ret = 0;
break;
case 0x1A:
ret = int1a_handler();
ret = 1;
break;
case 0xe6:
//ret = intE6_handler();
ret = 0;
break;
default:
break;
}
if (!ret)
ret = run_bios_int(num);
}
/*
* here we are really paranoid about faking a "real"
* BIOS. Most of this information was pulled from
* dosemu.
*/
static void setup_system_bios(void)
{
int i;
/* Set up Interrupt Vectors. The IVT starts at 0x0000:0x0000
* Additionally, we put some stub code into the F segment for
* those pesky little buggers that jmp to the hard coded addresses
* instead of calling int XX. This stub code looks like this
*
* CD XX int 0xXX
* C3 ret
* F4 hlt
*/
/* int 05 default location (Bound Exceeded) */
MEM_WL(0x05 << 2, 0xf000ff54);
MEM_WL(0xfff54, 0xf4c305cd);
/* int 08 default location (Double Fault) */
MEM_WL(0x08 << 2, 0xf000fea5);
MEM_WL(0xffea5, 0xf4c308cd);
/* int 0E default location (Page Fault) */
MEM_WL(0x0e << 2, 0xf000ef57);
MEM_WL(0xfef57, 0xf4c30ecd);
/* int 10 default location */
MEM_WL(0x10 << 2, 0xf000f065);
MEM_WL(0xff065, 0xf4c310cd);
/* int 11 default location (Get Equipment Configuration) */
MEM_WL(0x11 << 2, 0xf000f84d);
MEM_WL(0xff84d, 0xf4c311cd);
/* int 12 default location (Get Conventional Memory Size) */
MEM_WL(0x12 << 2, 0xf000f841);
MEM_WL(0xff841, 0xf4c312cd);
/* int 13 default location (Disk) */
MEM_WL(0x13 << 2, 0xf000ec59);
MEM_WL(0xfec59, 0xf4c313cd);
/* int 14 default location (Disk) */
MEM_WL(0x14 << 2, 0xf000e739);
MEM_WL(0xfe739, 0xf4c314cd);
/* int 15 default location (I/O System Extensions) */
MEM_WL(0x15 << 2, 0xf000f859);
MEM_WL(0xf859, 0xf4c315cd);
/* int 16 default location */
MEM_WL(0x16 << 2, 0xf000e82e);
MEM_WL(0xfe82e, 0xf4c316cd);
/* int 17 default location (Parallel Port) */
MEM_WL(0x17 << 2, 0xf000efd2);
MEM_WL(0xfefd2, 0xf4c317cd);
/* int 1A default location (RTC, PCI and others) */
MEM_WL(0x1a << 2, 0xf000fe6e);
MEM_WL(0xffe6e, 0xf4c31acd);
/* int 1E default location (FDD table) */
MEM_WL(0x1e << 2, 0xf000efc7);
MEM_WL(0xfefc7, 0xf4c31ecd);
/* font tables default location (int 1F) */
MEM_WL(0x1f << 2, 0xf000fa6e);
MEM_WL(0xffa6e, 0xf4c31fcd);
/* int 42 default location */
MEM_WL(0x42 << 2, 0xf000f065);
/* int 6D default location */
MEM_WL(0x6D << 2, 0xf000f065);
/* Clear EBDA */
for (i=(INITIAL_EBDA_SEGMENT << 4);
i<(INITIAL_EBDA_SEGMENT << 4) + INITIAL_EBDA_SIZE; i++)
MEM_WB(i, 0);
/* at offset 0h in EBDA is the size of the EBDA in KB */
MEM_WW((INITIAL_EBDA_SEGMENT << 4) + 0x0, INITIAL_EBDA_SIZE / 1024);
/* Clear BDA */
for (i=0x400; i<0x500; i+=4)
MEM_WL(i, 0);
/* Set up EBDA */
MEM_WW(0x40e, INITIAL_EBDA_SEGMENT);
/* Set RAM size to 16MB (fake) */
MEM_WW(0x413, 16384);
// TODO Set up more of BDA here
/* setup original ROM BIOS Area (F000:xxxx) */
const char *date = "06/23/99";
for (i = 0; date[i]; i++)
MEM_WB(0xffff5 + i, date[i]);
/* set up eisa ident string */
const char *ident = "PCI_ISA";
for (i = 0; ident[i]; i++)
MEM_WB(0xfffd9 + i, ident[i]);
// write system model id for IBM-AT
// according to "Ralf Browns Interrupt List" Int15 AH=C0 Table 515,
// model FC is the original AT and also used in all DOSEMU Versions.
MEM_WB(0xFFFFE, 0xfc);
}
#define BIOSEMU_MEM_BASE 0x00000000
#define BIOSEMU_MEM_SIZE 0x00100000
void run_bios(struct device * dev, unsigned long addr)
{
int i;
u16 initialcs = (addr & 0xF0000) >> 4;
u16 initialip = (addr + 3) & 0xFFFF;
u16 devfn = (dev->bus->secondary << 8) | dev->path.pci.devfn;
X86EMU_intrFuncs intFuncs[256];
X86EMU_setMemBase(BIOSEMU_MEM_BASE, BIOSEMU_MEM_SIZE);
X86EMU_setupPioFuncs(&biosemu_piofuncs);
for (i = 0; i < 256; i++)
intFuncs[i] = do_int;
X86EMU_setupIntrFuncs(intFuncs);
setup_system_bios();
/* cpu setup */
X86_AX = devfn ? devfn : 0xff;
X86_DX = 0x80;
X86_EIP = initialip;
X86_CS = initialcs;
/* Initialize stack and data segment */
X86_SS = STACK_SEGMENT;
X86_SP = STACK_START_OFFSET;;
X86_DS = DATA_SEGMENT;
/* We need a sane way to return from bios
* execution. A hlt instruction and a pointer
* to it, both kept on the stack, will do.
*/
push_word(0xf4f4); /* hlt; hlt */
push_word(X86_SS);
push_word(X86_SP + 2);
#ifdef DEBUG
//X86EMU_trace_on();
#endif
printk("Executing Initialization Vector...\n");
X86EMU_exec();
printk("Option ROM Exit Status: %04x\n", X86_AX);
/* Check whether the stack is "clean" i.e. containing the HLT
* instruction we pushed before executing and pointing to the original
* stack address... indicating that the initialization probably was
* successful
*/
if ((pop_word() == 0xf4f4) && (X86_SS == STACK_SEGMENT)
&& (X86_SP == STACK_START_OFFSET)) {
printk("Stack is clean, initialization successfull!\n");
} else {
printk("Stack unclean, initialization probably NOT COMPLETE!!\n");
printk("SS:SP = %04x:%04x, expected: %04x:%04x\n",
X86_SS, X86_SP, STACK_SEGMENT, STACK_START_OFFSET);
}
}

View File

@ -5,4 +5,5 @@ obj-y += interrupt.o
obj-y += io.o
obj-y += mem.o
obj-y += pmm.o
obj-y += vbe.o
subdirs-y += compat

View File

@ -86,10 +86,15 @@ biosemu(u8 *biosmem, u32 biosmem_size, struct device * dev, unsigned long rom_ad
// in case we jump somewhere unexpected, or execution is finished,
// fill the biosmem with hlt instructions (0xf4)
memset(biosmem, 0xf4, biosmem_size);
// But we have to be careful: If biosmem is 0x00000000 we're running
// in the lower 1MB and we must not wipe memory like that.
if (biosmem) {
DEBUG_PRINTF("Clearing biosmem\n");
memset(biosmem, 0xf4, biosmem_size);
}
X86EMU_setMemBase(biosmem, biosmem_size);
M.mem_base = (long) biosmem;
M.mem_size = biosmem_size;
DEBUG_PRINTF("membase set: %08x, size: %08x\n", (int) M.mem_base,
(int) M.mem_size);

View File

@ -16,24 +16,41 @@
#include <types.h>
#include <string.h>
#include <device/device.h>
#include "../debug.h"
#define VMEM_SIZE 1024 *1024 /* 1 MB */
#define VMEM_SIZE (1024 * 1024) /* 1 MB */
#if !defined(CONFIG_YABEL_DIRECTHW) || (!CONFIG_YABEL_DIRECTHW)
#ifdef CONFIG_YABEL_VIRTMEM_LOCATION
u8* vmem = (u8 *) CONFIG_YABEL_VIRTMEM_LOCATION;
#else
u8* vmem = (u8 *) (16*1024*1024); /* default to 16MB */
#endif
#else
u8* vmem = NULL;
#endif
u32 biosemu(u8 *biosmem, u32 biosmem_size, struct device *dev,
unsigned long rom_addr);
#if CONFIG_BOOTSPLASH
void vbe_set_graphics(void);
#endif
void run_bios(struct device * dev, unsigned long addr)
{
biosemu(vmem, VMEM_SIZE, dev, addr);
memcpy(0x0, vmem + 0x0, 0x400);
memcpy(0x400, vmem + 0x400, 0x100);
memcpy(0xc0000, vmem + 0xc0000, 0x10000);
#if CONFIG_BOOTSPLASH
vbe_set_graphics();
#endif
if (vmem != NULL) {
printf("Copying legacy memory from 0x%08x to the lower 1MB\n", vmem);
memcpy(0x00000, vmem + 0x00000, 0x400); // IVT
memcpy(0x00400, vmem + 0x00400, 0x100); // BDA
memcpy(0xc0000, vmem + 0xc0000, 0x10000); // VGA OPROM
}
}
u64 get_time(void)

View File

@ -80,6 +80,76 @@ inl(u16 port)
return 0;
}
#endif
#if defined(CONFIG_YABEL_DIRECTHW) && (CONFIG_YABEL_DIRECTHW == 1)
u8 my_inb(X86EMU_pioAddr addr)
{
u8 val;
val = inb(addr);
#ifdef CONFIG_DEBUG
if ((debug_flags & DEBUG_IO) && (addr != 0x40))
printk("inb(0x%04x) = 0x%02x\n", addr, val);
#endif
return val;
}
u16 my_inw(X86EMU_pioAddr addr)
{
u16 val;
val = inw(addr);
#ifdef CONFIG_DEBUG
if (debug_flags & DEBUG_IO)
printk("inw(0x%04x) = 0x%04x\n", addr, val);
#endif
return val;
}
u32 my_inl(X86EMU_pioAddr addr)
{
u32 val;
val = inl(addr);
#ifdef CONFIG_DEBUG
if (debug_flags & DEBUG_IO)
printk("inl(0x%04x) = 0x%08x\n", addr, val);
#endif
return val;
}
void my_outb(X86EMU_pioAddr addr, u8 val)
{
#ifdef CONFIG_DEBUG
if ((debug_flags & DEBUG_IO) && (addr != 0x43))
printk("outb(0x%02x, 0x%04x)\n", val, addr);
#endif
outb(val, addr);
}
void my_outw(X86EMU_pioAddr addr, u16 val)
{
#ifdef CONFIG_DEBUG
if (debug_flags & DEBUG_IO)
printk("outw(0x%04x, 0x%04x)\n", val, addr);
#endif
outw(val, addr);
}
void my_outl(X86EMU_pioAddr addr, u32 val)
{
#ifdef CONFIG_DEBUG
if (debug_flags & DEBUG_IO)
printk("outl(0x%08x, 0x%04x)\n", val, addr);
#endif
outl(val, addr);
}
#else
u32 pci_cfg_read(X86EMU_pioAddr addr, u8 size);
void pci_cfg_write(X86EMU_pioAddr addr, u32 val, u8 size);
u8 handle_port_61h(void);
@ -479,3 +549,4 @@ handle_port_61h(void)
//finally read the value from the io_buffer
return *((u8 *) (bios_device.io_buffer + 0x61));
}
#endif

View File

@ -168,6 +168,7 @@ extern u64 get_time(void);
void update_time(u32);
#if !defined(CONFIG_YABEL_DIRECTHW) || (!CONFIG_YABEL_DIRECTHW)
// read byte from memory
u8
my_rdb(u32 addr)
@ -436,6 +437,43 @@ my_wrl(u32 addr, u32 val)
out32le((void *) (M.mem_base + addr), val);
}
}
#else
u8
my_rdb(u32 addr)
{
return rdb(addr);
}
u16
my_rdw(u32 addr)
{
return rdw(addr);
}
u32
my_rdl(u32 addr)
{
return rdl(addr);
}
void
my_wrb(u32 addr, u8 val)
{
wrb(addr, val);
}
void
my_wrw(u32 addr, u16 val)
{
wrw(addr, val);
}
void
my_wrl(u32 addr, u32 val)
{
wrl(addr, val);
}
#endif
//update time in BIOS Data Area
//DWord at offset 0x6c is the timer ticks since midnight, timer is running at 18Hz

View File

@ -13,6 +13,12 @@
#include <string.h>
#include <types.h>
#if CONFIG_BOOTSPLASH
#include <boot/coreboot_tables.h>
#endif
#include <arch/byteorder.h>
#define ntohl(x) be32_to_cpu(x)
#include "debug.h"
@ -26,18 +32,14 @@
#include "interrupt.h"
#include "device.h"
static X86EMU_memFuncs my_mem_funcs = {
my_rdb, my_rdw, my_rdl,
my_wrb, my_wrw, my_wrl
};
#include <cbfs.h>
static X86EMU_pioFuncs my_pio_funcs = {
my_inb, my_inw, my_inl,
my_outb, my_outw, my_outl
};
#include <delay.h>
#include "../../src/lib/jpeg.h"
// pointer to VBEInfoBuffer, set by vbe_prepare
u8 *vbe_info_buffer = 0;
// virtual BIOS Memory
u8 *biosmem;
u32 biosmem_size;
@ -72,18 +74,58 @@ typedef struct {
u16 total_memory;
} vbe_info_t;
typedef struct {
u16 mode_attributes; // 00
u8 win_a_attributes; // 02
u8 win_b_attributes; // 03
u16 win_granularity; // 04
u16 win_size; // 06
u16 win_a_segment; // 08
u16 win_b_segment; // 0a
u32 win_func_ptr; // 0c
u16 bytes_per_scanline; // 10
u16 x_resolution; // 12
u16 y_resolution; // 14
u8 x_charsize; // 16
u8 y_charsize; // 17
u8 number_of_planes; // 18
u8 bits_per_pixel; // 19
u8 number_of_banks; // 20
u8 memory_model; // 21
u8 bank_size; // 22
u8 number_of_image_pages; // 23
u8 reserved_page;
u8 red_mask_size;
u8 red_mask_pos;
u8 green_mask_size;
u8 green_mask_pos;
u8 blue_mask_size;
u8 blue_mask_pos;
u8 reserved_mask_size;
u8 reserved_mask_pos;
u8 direct_color_mode_info;
u32 phys_base_ptr;
u32 offscreen_mem_offset;
u16 offscreen_mem_size;
u8 reserved[206];
} __attribute__ ((__packed__)) vesa_mode_info_t;
typedef struct {
u16 video_mode;
u8 mode_info_block[256];
u16 attributes;
u16 linebytes;
u16 x_resolution;
u16 y_resolution;
u8 x_charsize;
u8 y_charsize;
u8 bits_per_pixel;
u8 memory_model;
u32 framebuffer_address;
union {
vesa_mode_info_t vesa;
u8 mode_info_block[256];
};
// our crap
//u16 attributes;
//u16 linebytes;
//u16 x_resolution;
//u16 y_resolution;
//u8 x_charsize;
//u8 y_charsize;
//u8 bits_per_pixel;
//u8 memory_model;
//u32 framebuffer_address;
} vbe_mode_info_t;
typedef struct {
@ -94,7 +136,7 @@ typedef struct {
} vbe_ddc_info_t;
static inline u8
vbe_prepare()
vbe_prepare(void)
{
vbe_info_buffer = biosmem + (VBE_SEGMENT << 4); // segment:offset off VBE Data Area
//clear buffer
@ -209,6 +251,7 @@ vbe_get_mode_info(vbe_mode_info_t * mode_info)
__func__, mode_info->video_mode, M.x86.R_AH);
return M.x86.R_AH;
}
//pointer to mode_info_block is in ES:DI
memcpy(mode_info->mode_info_block,
biosmem + ((M.x86.R_ES << 4) + M.x86.R_DI),
@ -217,34 +260,6 @@ vbe_get_mode_info(vbe_mode_info_t * mode_info)
//printf("Mode Info Dump:");
//dump(mode_info_block, 64);
// offset 0: 16bit le mode attributes
mode_info->attributes = in16le(mode_info->mode_info_block);
// offset 16: 16bit le bytes per scan line
mode_info->linebytes = in16le(mode_info->mode_info_block + 16);
// offset 18: 16bit le x resolution
mode_info->x_resolution = in16le(mode_info->mode_info_block + 18);
// offset 20: 16bit le y resolution
mode_info->y_resolution = in16le(mode_info->mode_info_block + 20);
// offset 22: 8bit le x charsize
mode_info->x_charsize = *(mode_info->mode_info_block + 22);
// offset 23: 8bit le y charsize
mode_info->y_charsize = *(mode_info->mode_info_block + 23);
// offset 25: 8bit le bits per pixel
mode_info->bits_per_pixel = *(mode_info->mode_info_block + 25);
// offset 27: 8bit le memory model
mode_info->memory_model = *(mode_info->mode_info_block + 27);
// offset 40: 32bit le containg offset of frame buffer memory ptr
mode_info->framebuffer_address =
in32le(mode_info->mode_info_block + 40);
return 0;
}
@ -482,56 +497,22 @@ vbe_get_ddc_info(vbe_ddc_info_t * ddc_info)
}
u32
vbe_get_info(u8 argc, char ** argv)
vbe_get_info(void)
{
u8 rval;
u32 i;
if (argc < 4) {
printf
("Usage %s <vmem_base> <device_path> <address of screen_info_t>\n",
argv[0]);
int i = 0;
for (i = 0; i < argc; i++) {
printf("argv[%d]: %s\n", i, argv[i]);
}
return -1;
}
int i;
// XXX FIXME these need to be filled with sane values
// get a copy of input struct...
screen_info_input_t input =
*((screen_info_input_t *) strtoul((char *) argv[4], 0, 16));
screen_info_input_t input;
// output is pointer to the address passed as argv[4]
screen_info_t *output =
(screen_info_t *) strtoul((char *) argv[4], 0, 16);
screen_info_t local_output;
screen_info_t *output = &local_output;
// zero input
memset(&input, 0, sizeof(screen_info_input_t));
// zero output
memset(output, 0, sizeof(screen_info_t));
// argv[1] is address of virtual BIOS mem...
// argv[2] is the size
biosmem = (u8 *) strtoul(argv[1], 0, 16);
biosmem_size = strtoul(argv[2], 0, 16);;
if (biosmem_size < MIN_REQUIRED_VMEM_SIZE) {
printf("Error: Not enough virtual memory: %x, required: %x!\n",
biosmem_size, MIN_REQUIRED_VMEM_SIZE);
return -1;
}
// argv[3] is the device to open and use...
if (dev_init((char *) argv[3]) != 0) {
printf("Error initializing device!\n");
return -1;
}
//setup interrupt handler
X86EMU_intrFuncs intrFuncs[256];
for (i = 0; i < 256; i++)
intrFuncs[i] = handleInterrupt;
X86EMU_setupIntrFuncs(intrFuncs);
X86EMU_setupPioFuncs(&my_pio_funcs);
X86EMU_setupMemFuncs(&my_mem_funcs);
// set mem_base
M.mem_base = (long) biosmem;
M.mem_size = biosmem_size;
DEBUG_PRINTF_VBE("membase set: %08x, size: %08x\n", (int) M.mem_base,
(int) M.mem_size);
memset(&output, 0, sizeof(screen_info_t));
vbe_info_t info;
rval = vbe_info(&info);
@ -613,7 +594,9 @@ vbe_get_info(u8 argc, char ** argv)
while ((mode_info.video_mode = info.video_mode_list[i]) != 0xFFFF) {
//DEBUG_PRINTF_VBE("%x: Mode: %04x\n", i, mode_info.video_mode);
vbe_get_mode_info(&mode_info);
#if 0
// FIXME all these values are little endian!
DEBUG_PRINTF_VBE("Video Mode 0x%04x available, %s\n",
mode_info.video_mode,
(mode_info.attributes & 0x1) ==
@ -646,13 +629,13 @@ vbe_get_info(u8 argc, char ** argv)
mode_info.memory_model);
DEBUG_PRINTF_VBE("\tFramebuffer Offset: %08x\n",
mode_info.framebuffer_address);
#endif
if ((mode_info.bits_per_pixel == input.color_depth)
&& (mode_info.x_resolution <= input.max_screen_width)
&& ((mode_info.attributes & 0x80) != 0) // framebuffer mode
&& ((mode_info.attributes & 0x10) != 0) // graphics
&& ((mode_info.attributes & 0x8) != 0) // color
&& (mode_info.x_resolution > best_mode_info.x_resolution)) // better than previous best_mode
if ((mode_info.vesa.bits_per_pixel == input.color_depth)
&& (le16_to_cpu(mode_info.vesa.x_resolution) <= input.max_screen_width)
&& ((le16_to_cpu(mode_info.vesa.mode_attributes) & 0x80) != 0) // framebuffer mode
&& ((le16_to_cpu(mode_info.vesa.mode_attributes) & 0x10) != 0) // graphics
&& ((le16_to_cpu(mode_info.vesa.mode_attributes) & 0x8) != 0) // color
&& (le16_to_cpu(mode_info.vesa.x_resolution) > le16_to_cpu(best_mode_info.vesa.x_resolution))) // better than previous best_mode
{
// yiiiihaah... we found a new best mode
memcpy(&best_mode_info, &mode_info, sizeof(mode_info));
@ -757,12 +740,12 @@ vbe_get_info(u8 argc, char ** argv)
vbe_set_color(0x00, 0x00000000);
vbe_set_color(0xFF, 0x00FFFFFF);
output->screen_width = best_mode_info.x_resolution;
output->screen_height = best_mode_info.y_resolution;
output->screen_linebytes = best_mode_info.linebytes;
output->color_depth = best_mode_info.bits_per_pixel;
output->screen_width = le16_to_cpu(best_mode_info.vesa.x_resolution);
output->screen_height = le16_to_cpu(best_mode_info.vesa.y_resolution);
output->screen_linebytes = le16_to_cpu(best_mode_info.vesa.bytes_per_scanline);
output->color_depth = best_mode_info.vesa.bits_per_pixel;
output->framebuffer_address =
best_mode_info.framebuffer_address;
le32_to_cpu(best_mode_info.vesa.phys_base_ptr);
} else {
printf("%s: No suitable video mode found!\n", __func__);
//unset display_type...
@ -770,3 +753,92 @@ vbe_get_info(u8 argc, char ** argv)
}
return 0;
}
#if CONFIG_BOOTSPLASH
vbe_mode_info_t mode_info;
void vbe_set_graphics(void)
{
u8 rval;
int i;
vbe_info_t info;
rval = vbe_info(&info);
if (rval != 0)
return;
DEBUG_PRINTF_VBE("VbeSignature: %s\n", info.signature);
DEBUG_PRINTF_VBE("VbeVersion: 0x%04x\n", info.version);
DEBUG_PRINTF_VBE("OemString: %s\n", info.oem_string_ptr);
DEBUG_PRINTF_VBE("Capabilities:\n");
DEBUG_PRINTF_VBE("\tDAC: %s\n",
(info.capabilities & 0x1) ==
0 ? "fixed 6bit" : "switchable 6/8bit");
DEBUG_PRINTF_VBE("\tVGA: %s\n",
(info.capabilities & 0x2) ==
0 ? "compatible" : "not compatible");
DEBUG_PRINTF_VBE("\tRAMDAC: %s\n",
(info.capabilities & 0x4) ==
0 ? "normal" : "use blank bit in Function 09h");
mode_info.video_mode = (1 << 14) | CONFIG_FRAMEBUFFER_VESA_MODE;
vbe_get_mode_info(&mode_info);
unsigned char *framebuffer =
(unsigned char *) le32_to_cpu(mode_info.vesa.phys_base_ptr);
DEBUG_PRINTF_VBE("FRAMEBUFFER: 0x%08x\n", framebuffer);
vbe_set_mode(&mode_info);
struct jpeg_decdata *decdata;
decdata = malloc(sizeof(*decdata));
/* Switching Intel IGD to 1MB video memory will break this. Who
* cares. */
int imagesize = 1024*768*2;
struct cbfs_file *file = cbfs_find("bootsplash.jpg");
if (!file) {
DEBUG_PRINTF_VBE("Could not find bootsplash.jpg\n");
return;
}
unsigned char *jpeg = ((unsigned char *)file) + ntohl(file->offset);
DEBUG_PRINTF_VBE("Splash at %08x ...\n", jpeg);
dump(jpeg, 64);
int ret = 0;
DEBUG_PRINTF_VBE("Decompressing boot splash screen...\n");
ret = jpeg_decode(jpeg, framebuffer, 1024, 768, 16, decdata);
DEBUG_PRINTF_VBE("returns %x\n", ret);
}
void fill_lb_framebuffer(struct lb_framebuffer *framebuffer)
{
framebuffer->physical_address = le32_to_cpu(mode_info.vesa.phys_base_ptr);
framebuffer->x_resolution = le16_to_cpu(mode_info.vesa.x_resolution);
framebuffer->y_resolution = le16_to_cpu(mode_info.vesa.y_resolution);
framebuffer->bytes_per_line = le16_to_cpu(mode_info.vesa.bytes_per_scanline);
framebuffer->bits_per_pixel = mode_info.vesa.bits_per_pixel;
framebuffer->red_mask_pos = mode_info.vesa.red_mask_pos;
framebuffer->red_mask_size = mode_info.vesa.red_mask_size;
framebuffer->green_mask_pos = mode_info.vesa.green_mask_pos;
framebuffer->green_mask_size = mode_info.vesa.green_mask_size;
framebuffer->blue_mask_pos = mode_info.vesa.blue_mask_pos;
framebuffer->blue_mask_size = mode_info.vesa.blue_mask_size;
framebuffer->reserved_mask_pos = mode_info.vesa.reserved_mask_pos;
framebuffer->reserved_mask_size = mode_info.vesa.reserved_mask_size;
}
void vbe_textmode_console(void)
{
/* Wait, just a little bit more, pleeeease ;-) */
delay(2);
M.x86.R_EAX = 0x0003;
runInt10();
}
#endif