87 changes: 79 additions & 8 deletions src/hw/virtio-scsi.c
Expand Up @@ -18,14 +18,17 @@
#include "stacks.h" // run_thread
#include "std/disk.h" // DISK_RET_SUCCESS
#include "string.h" // memset
#include "util.h" // usleep
#include "util.h" // usleep, bootprio_find_pci_device, is_bootprio_strict
#include "virtio-pci.h"
#include "virtio-ring.h"
#include "virtio-scsi.h"
#include "virtio-mmio.h"

struct virtio_lun_s {
struct drive_s drive;
struct pci_device *pci;
void *mmio;
char name[16];
struct vring_virtqueue *vq;
struct vp_device *vp;
u16 target;
Expand Down Expand Up @@ -94,34 +97,57 @@ virtio_scsi_process_op(struct disk_op_s *op)
}

static void
virtio_scsi_init_lun(struct virtio_lun_s *vlun, struct pci_device *pci,
virtio_scsi_init_lun(struct virtio_lun_s *vlun,
struct pci_device *pci, void *mmio,
struct vp_device *vp, struct vring_virtqueue *vq,
u16 target, u16 lun)
{
memset(vlun, 0, sizeof(*vlun));
vlun->drive.type = DTYPE_VIRTIO_SCSI;
vlun->drive.cntl_id = pci->bdf;
vlun->pci = pci;
vlun->mmio = mmio;
vlun->vp = vp;
vlun->vq = vq;
vlun->target = target;
vlun->lun = lun;
if (vlun->pci)
snprintf(vlun->name, sizeof(vlun->name), "pci:%pP", vlun->pci);
if (vlun->mmio)
snprintf(vlun->name, sizeof(vlun->name), "mmio:%08x", (u32)vlun->mmio);
}

static int
virtio_scsi_add_lun(u32 lun, struct drive_s *tmpl_drv)
{
u8 skip_nonbootable = is_bootprio_strict();
struct virtio_lun_s *tmpl_vlun =
container_of(tmpl_drv, struct virtio_lun_s, drive);
int prio = -1;

if (tmpl_vlun->pci)
prio = bootprio_find_scsi_device(tmpl_vlun->pci, tmpl_vlun->target, lun);
if (tmpl_vlun->mmio)
prio = bootprio_find_scsi_mmio_device(tmpl_vlun->mmio, tmpl_vlun->target, lun);

if (skip_nonbootable && prio < 0) {
dprintf(1, "skipping init of a non-bootable virtio-scsi dev at %s,"
" target %d, lun %d\n",
tmpl_vlun->name, tmpl_vlun->target, lun);
return -1;
}

struct virtio_lun_s *vlun = malloc_low(sizeof(*vlun));
if (!vlun) {
warn_noalloc();
return -1;
}
virtio_scsi_init_lun(vlun, tmpl_vlun->pci, tmpl_vlun->vp, tmpl_vlun->vq,
tmpl_vlun->target, lun);
virtio_scsi_init_lun(vlun, tmpl_vlun->pci, tmpl_vlun->mmio,tmpl_vlun->vp,
tmpl_vlun->vq, tmpl_vlun->target, lun);

int prio = bootprio_find_scsi_device(vlun->pci, vlun->target, vlun->lun);
if (vlun->pci)
boot_lchs_find_scsi_device(vlun->pci, vlun->target, vlun->lun,
&(vlun->drive.lchs));
int ret = scsi_drive_setup(&vlun->drive, "virtio-scsi", prio);
if (ret)
goto fail;
Expand All @@ -133,13 +159,13 @@ virtio_scsi_add_lun(u32 lun, struct drive_s *tmpl_drv)
}

static int
virtio_scsi_scan_target(struct pci_device *pci, struct vp_device *vp,
virtio_scsi_scan_target(struct pci_device *pci, void *mmio, struct vp_device *vp,
struct vring_virtqueue *vq, u16 target)
{

struct virtio_lun_s vlun0;

virtio_scsi_init_lun(&vlun0, pci, vp, vq, target, 0);
virtio_scsi_init_lun(&vlun0, pci, mmio, vp, vq, target, 0);

int ret = scsi_rep_luns_scan(&vlun0.drive, virtio_scsi_add_lun);
return ret < 0 ? 0 : ret;
Expand Down Expand Up @@ -187,7 +213,43 @@ init_virtio_scsi(void *data)

int i, tot;
for (tot = 0, i = 0; i < 256; i++)
tot += virtio_scsi_scan_target(pci, vp, vq, i);
tot += virtio_scsi_scan_target(pci, NULL, vp, vq, i);

if (!tot)
goto fail;

return;

fail:
vp_reset(vp);
free(vp);
free(vq);
}

void
init_virtio_scsi_mmio(void *mmio)
{
dprintf(1, "found virtio-scsi-mmio at %p\n", mmio);
struct vring_virtqueue *vq = NULL;
struct vp_device *vp = malloc_high(sizeof(*vp));
if (!vp) {
warn_noalloc();
return;
}
vp_init_mmio(vp, mmio);
u8 status = VIRTIO_CONFIG_S_ACKNOWLEDGE | VIRTIO_CONFIG_S_DRIVER;

if (vp_find_vq(vp, 2, &vq) < 0 ) {
dprintf(1, "fail to find vq for virtio-scsi-mmio %p\n", mmio);
goto fail;
}

status |= VIRTIO_CONFIG_S_DRIVER_OK;
vp_set_status(vp, status);

int i, tot;
for (tot = 0, i = 0; i < 256; i++)
tot += virtio_scsi_scan_target(NULL, mmio, vp, vq, i);

if (!tot)
goto fail;
Expand All @@ -203,6 +265,8 @@ init_virtio_scsi(void *data)
void
virtio_scsi_setup(void)
{
u8 skip_nonbootable = is_bootprio_strict();

ASSERT32FLAT();
if (! CONFIG_VIRTIO_SCSI)
return;
Expand All @@ -215,6 +279,13 @@ virtio_scsi_setup(void)
(pci->device != PCI_DEVICE_ID_VIRTIO_SCSI_09 &&
pci->device != PCI_DEVICE_ID_VIRTIO_SCSI_10))
continue;

if (skip_nonbootable && bootprio_find_pci_device(pci) < 0) {
dprintf(1, "skipping init of a non-bootable virtio-scsi at %pP\n",
pci);
continue;
}

run_thread(init_virtio_scsi, pci);
}
}
1 change: 1 addition & 0 deletions src/hw/virtio-scsi.h
Expand Up @@ -43,5 +43,6 @@ struct virtio_scsi_resp_cmd {
struct disk_op_s;
int virtio_scsi_process_op(struct disk_op_s *op);
void virtio_scsi_setup(void);
void init_virtio_scsi_mmio(void *data);

#endif /* _VIRTIO_SCSI_H */
32 changes: 32 additions & 0 deletions src/optionroms.c
Expand Up @@ -8,6 +8,7 @@
#include "bregs.h" // struct bregs
#include "config.h" // CONFIG_*
#include "farptr.h" // FLATPTR_TO_SEG
#include "biosvar.h" // GET_IVT
#include "hw/pci.h" // pci_config_readl
#include "hw/pcidevice.h" // foreachpci
#include "hw/pci_ids.h" // PCI_CLASS_DISPLAY_VGA
Expand Down Expand Up @@ -138,6 +139,14 @@ init_optionrom(struct rom_header *rom, u16 bdf, int isvga)

//TODO: Find a way to hide initialisation string of iPXE
//which was printed by calling callrom function
// It is called everytime and I have no idea how it was hidden before.
// For now it can be commented out and seems to work good.

/*
if (isvga || get_pnp_rom(newrom))
// Only init vga and PnP roms here.
callrom(newrom, bdf);
*/

if (isvga)
// Only init vga roms here.
Expand Down Expand Up @@ -314,6 +323,19 @@ map_pcirom(struct pci_device *pci)
return NULL;
}

static int boot_irq_captured(void)
{
return GET_IVT(0x19).segoff != FUNC16(entry_19_official).segoff;
}

static void boot_irq_restore(void)
{
struct segoff_s seabios;

seabios = FUNC16(entry_19_official);
SET_IVT(0x19, seabios);
}

// Attempt to map and initialize the option rom on a given PCI device.
static void
init_pcirom(struct pci_device *pci, int isvga, u64 *sources)
Expand All @@ -333,8 +355,18 @@ init_pcirom(struct pci_device *pci, int isvga, u64 *sources)
if (! rom)
// No ROM present.
return;
int irq_was_captured = boot_irq_captured();
struct pnp_data *pnp = get_pnp_rom(rom);
setRomSource(sources, rom, RS_PCIROM | (u32)pci);
init_optionrom(rom, pci->bdf, isvga);
if (boot_irq_captured() && !irq_was_captured &&
!file && !isvga && pnp) {
// This PCI rom is misbehaving - recapture the boot irqs
char *desc = MAKE_FLATPTR(FLATPTR_TO_SEG(rom), pnp->productname);
dprintf(1, "PnP optionrom \"%s\" (bdf %pP) captured int19, restoring\n",
desc, pci);
boot_irq_restore();
}
}


Expand Down
49 changes: 27 additions & 22 deletions src/output.c
Expand Up @@ -160,34 +160,36 @@ putuint(struct putcinfo *action, u32 val)

// Output a single digit hex character.
static inline void
putsinglehex(struct putcinfo *action, u32 val)
putsinglehex(struct putcinfo *action, u32 val, int uc)
{
if (val <= 9)
val = '0' + val;
else if (uc)
val = 'A' + val - 10;
else
val = 'a' + val - 10;
putc(action, val);
}

// Output an integer in hexadecimal with a specified width.
static void
puthex(struct putcinfo *action, u32 val, int width)
puthex(struct putcinfo *action, u32 val, int width, int uc)
{
switch (width) {
default: putsinglehex(action, (val >> 28) & 0xf);
case 7: putsinglehex(action, (val >> 24) & 0xf);
case 6: putsinglehex(action, (val >> 20) & 0xf);
case 5: putsinglehex(action, (val >> 16) & 0xf);
case 4: putsinglehex(action, (val >> 12) & 0xf);
case 3: putsinglehex(action, (val >> 8) & 0xf);
case 2: putsinglehex(action, (val >> 4) & 0xf);
case 1: putsinglehex(action, (val >> 0) & 0xf);
default: putsinglehex(action, (val >> 28) & 0xf, uc);
case 7: putsinglehex(action, (val >> 24) & 0xf, uc);
case 6: putsinglehex(action, (val >> 20) & 0xf, uc);
case 5: putsinglehex(action, (val >> 16) & 0xf, uc);
case 4: putsinglehex(action, (val >> 12) & 0xf, uc);
case 3: putsinglehex(action, (val >> 8) & 0xf, uc);
case 2: putsinglehex(action, (val >> 4) & 0xf, uc);
case 1: putsinglehex(action, (val >> 0) & 0xf, uc);
}
}

// Output an integer in hexadecimal with a minimum width.
static void
putprettyhex(struct putcinfo *action, u32 val, int width, char padchar)
putprettyhex(struct putcinfo *action, u32 val, int width, char padchar, int uc)
{
u32 tmp = val;
int count = 1;
Expand All @@ -196,18 +198,18 @@ putprettyhex(struct putcinfo *action, u32 val, int width, char padchar)
width -= count;
while (width-- > 0)
putc(action, padchar);
puthex(action, val, count);
puthex(action, val, count, uc);
}

// Output 'struct pci_device' BDF as %02x:%02x.%x
static void
put_pci_device(struct putcinfo *action, struct pci_device *pci)
{
puthex(action, pci_bdf_to_bus(pci->bdf), 2);
puthex(action, pci_bdf_to_bus(pci->bdf), 2, 0);
putc(action, ':');
puthex(action, pci_bdf_to_dev(pci->bdf), 2);
puthex(action, pci_bdf_to_dev(pci->bdf), 2, 0);
putc(action, '.');
puthex(action, pci_bdf_to_fn(pci->bdf), 1);
puthex(action, pci_bdf_to_fn(pci->bdf), 1, 0);
}

static inline int
Expand All @@ -220,6 +222,7 @@ static void
bvprintf(struct putcinfo *action, const char *fmt, va_list args)
{
const char *s = fmt;
int uc;
for (;; s++) {
char c = GET_GLOBAL(*(u8*)s);
if (!c)
Expand Down Expand Up @@ -284,19 +287,21 @@ bvprintf(struct putcinfo *action, const char *fmt, va_list args)
}
putc(action, '0');
putc(action, 'x');
puthex(action, val, 8);
puthex(action, val, 8, 0);
break;
case 'X':
case 'x':
uc = (c == 'X');
val = va_arg(args, s32);
if (is64) {
u32 upper = va_arg(args, s32);
if (upper) {
putprettyhex(action, upper, field_width - 8, padchar);
puthex(action, val, 8);
putprettyhex(action, upper, field_width - 8, padchar, uc);
puthex(action, val, 8, uc);
break;
}
}
putprettyhex(action, val, field_width, padchar);
putprettyhex(action, val, field_width, padchar, uc);
break;
case 'c':
val = va_arg(args, int);
Expand Down Expand Up @@ -348,7 +353,7 @@ __dprintf(const char *fmt, ...)
if (cur != &MainThread) {
// Show "thread id" for this debug message.
debug_putc(&debuginfo, '|');
puthex(&debuginfo, (u32)cur, 8);
puthex(&debuginfo, (u32)cur, 8, 0);
debug_putc(&debuginfo, '|');
debug_putc(&debuginfo, ' ');
}
Expand Down Expand Up @@ -450,12 +455,12 @@ hexdump(const void *d, int len)
while (len > 0) {
if (count % 8 == 0) {
putc(&debuginfo, '\n');
puthex(&debuginfo, count*4, 8);
puthex(&debuginfo, count*4, 8, 0);
putc(&debuginfo, ':');
} else {
putc(&debuginfo, ' ');
}
puthex(&debuginfo, *(u32*)d, 8);
puthex(&debuginfo, *(u32*)d, 8, 0);
count++;
len-=4;
d+=4;
Expand Down
2 changes: 2 additions & 0 deletions src/post.c
Expand Up @@ -10,6 +10,7 @@
#include "bregs.h" // struct bregs
#include "config.h" // CONFIG_*
#include "e820map.h" // e820_add
#include "fmap.h" // find_fmap_directory
#include "fw/paravirt.h" // qemu_cfg_preinit
#include "fw/xen.h" // xen_preinit
#include "hw/pic.h" // pic_setup
Expand Down Expand Up @@ -107,6 +108,7 @@ interface_init(void)
// Setup romfile items.
qemu_cfg_init();
coreboot_cbfs_init();
find_fmap_directory();
multiboot_init();

// Setup ivt/bda/ebda
Expand Down
47 changes: 44 additions & 3 deletions src/romfile.c
Expand Up @@ -9,6 +9,7 @@
#include "output.h" // dprintf
#include "romfile.h" // struct romfile_s
#include "string.h" // memcmp
#include "fw/coreboot.h" // cbfs_romfile overrides

static struct romfile_s *RomfileRoot VARVERIFY32INIT;

Expand All @@ -28,8 +29,16 @@ __romfile_findprefix(const char *prefix, int prefixlen, struct romfile_s *prev)
if (prev)
cur = prev->next;
while (cur) {
if (memcmp(prefix, cur->name, prefixlen) == 0)
return cur;
if (memcmp(prefix, cur->name, prefixlen) == 0) {

int dont_hide;
// Check if we should hide this
char *data = get_cbmem_file( (char *) cur->name, &dont_hide );
if (!data) // no override for this file
return cur;
if (dont_hide) // We know it and shouldn't hide
return cur;
}
cur = cur->next;
}
return NULL;
Expand All @@ -52,6 +61,17 @@ romfile_find(const char *name)
void *
romfile_loadfile(const char *name, int *psize)
{
// First try to read a file override from cbmem
char *data = get_cbmem_file( (char *) name, psize );

if ( data ) {
if ( !*psize ) {
dprintf(3, "Hiding romfile '%s'\n", name);
return NULL;
}
return data;
}

struct romfile_s *file = romfile_find(name);
if (!file)
return NULL;
Expand All @@ -60,7 +80,7 @@ romfile_loadfile(const char *name, int *psize)
if (!filesize)
return NULL;

char *data = malloc_tmphigh(filesize+1);
data = malloc_tmphigh(filesize+1);
if (!data) {
warn_noalloc();
return NULL;
Expand All @@ -83,6 +103,27 @@ romfile_loadfile(const char *name, int *psize)
u64
romfile_loadint(const char *name, u64 defval)
{
int size;

// First try to read a file override from cbmem
char *data = get_cbmem_file( (char *) name, &size );

if ( data ) {
u64 val = 0;

switch (size){
case 1:
case 2:
case 4:
case 8:
memcpy(&val, data, size);
break;
default:
return defval;
}
return val;
}

struct romfile_s *file = romfile_find(name);
if (!file)
return defval;
Expand Down
2 changes: 1 addition & 1 deletion src/sercon.c
Expand Up @@ -468,7 +468,7 @@ static void sercon_104f(struct bregs *regs)
regs->ax = 0x0100;
} else {
// Disable sercon entry point on any vesa modeset
if (regs->al == 0x00)
if (regs->al == 0x02)
SET_LOW(sercon_enable, 0);
}
}
Expand Down
11 changes: 11 additions & 0 deletions src/std/acpi.h
Expand Up @@ -132,6 +132,17 @@ struct rsdt_descriptor_rev1
/* ACPI tables */
} PACKED;

/*
* ACPI 2.0 eXtended System Description Table (XSDT)
*/
#define XSDT_SIGNATURE 0x54445358 // XSDT
struct xsdt_descriptor_rev2
{
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
u64 table_offset_entry[0]; /* Array of pointers to other */
/* ACPI tables */
} PACKED;

/*
* ACPI 1.0 Firmware ACPI Control Structure (FACS)
*/
Expand Down
11 changes: 10 additions & 1 deletion src/std/tcg.h
Expand Up @@ -8,6 +8,9 @@
#define SHA384_BUFSIZE 48
#define SHA512_BUFSIZE 64
#define SM3_256_BUFSIZE 32
#define SHA3_256_BUFSIZE 32
#define SHA3_384_BUFSIZE 48
#define SHA3_512_BUFSIZE 64


/****************************************************************
Expand Down Expand Up @@ -335,12 +338,18 @@ struct tpm_res_sha1complete {
#define TPM2_ALG_SHA384 0x000c
#define TPM2_ALG_SHA512 0x000d
#define TPM2_ALG_SM3_256 0x0012
#define TPM2_ALG_SHA3_256 0x0027
#define TPM2_ALG_SHA3_384 0x0028
#define TPM2_ALG_SHA3_512 0x0029

#define TPM2_ALG_SHA1_FLAG (1 << 0)
#define TPM2_ALG_SHA256_FLAG (1 << 1)
#define TPM2_ALG_SHA384_FLAG (1 << 2)
#define TPM2_ALG_SHA512_FLAG (1 << 3)
#define TPM2_ALG_SM3_256_FLAG (1 << 4)
#define TPM2_ALG_SHA3_256_FLAG (1 << 5)
#define TPM2_ALG_SHA3_384_FLAG (1 << 6)
#define TPM2_ALG_SHA3_512_FLAG (1 << 7)

/* TPM 2 command tags */
#define TPM2_ST_NO_SESSIONS 0x8001
Expand Down Expand Up @@ -524,7 +533,7 @@ struct TCG_EfiSpecIdEventStruct {
struct TCG_EfiSpecIdEventAlgorithmSize {
u16 algorithmId;
u16 digestSize;
} digestSizes[0];
} digestSizes[];
/*
u8 vendorInfoSize;
u8 vendorInfo[0];
Expand Down
72 changes: 57 additions & 15 deletions src/tcgbios.c
Expand Up @@ -156,9 +156,10 @@ static struct tpml_pcr_selection *tpm20_pcr_selection;
struct tpm_log_entry {
struct tpm_log_header hdr;
u8 pad[sizeof(struct tpm2_digest_values)
+ 5 * sizeof(struct tpm2_digest_value)
+ 8 * sizeof(struct tpm2_digest_value)
+ SHA1_BUFSIZE + SHA256_BUFSIZE + SHA384_BUFSIZE
+ SHA512_BUFSIZE + SM3_256_BUFSIZE];
+ SHA512_BUFSIZE + SM3_256_BUFSIZE + SHA3_256_BUFSIZE
+ SHA3_384_BUFSIZE + SHA3_512_BUFSIZE];
} PACKED;

static const struct hash_parameters {
Expand Down Expand Up @@ -192,6 +193,21 @@ static const struct hash_parameters {
.hashalg_flag = TPM2_ALG_SM3_256_FLAG,
.hash_buffersize = SM3_256_BUFSIZE,
.name = "SM3-256",
}, {
.hashalg = TPM2_ALG_SHA3_256,
.hashalg_flag = TPM2_ALG_SHA3_256_FLAG,
.hash_buffersize = SHA3_256_BUFSIZE,
.name = "SHA3-256",
}, {
.hashalg = TPM2_ALG_SHA3_384,
.hashalg_flag = TPM2_ALG_SHA3_384_FLAG,
.hash_buffersize = SHA3_384_BUFSIZE,
.name = "SHA3-384",
}, {
.hashalg = TPM2_ALG_SHA3_512,
.hashalg_flag = TPM2_ALG_SHA3_512_FLAG,
.hash_buffersize = SHA3_512_BUFSIZE,
.name = "SHA3-512",
}
};

Expand Down Expand Up @@ -252,7 +268,7 @@ tpm20_write_EfiSpecIdEventStruct(void)

struct {
struct TCG_EfiSpecIdEventStruct hdr;
u8 pad[256];
u8 pad[sizeof(struct tpm_log_entry) + sizeof(u8)];
} event = {
.hdr.signature = "Spec ID Event03",
.hdr.platformClass = TPM_TCPA_ACPI_CLASS_CLIENT,
Expand All @@ -265,14 +281,19 @@ tpm20_write_EfiSpecIdEventStruct(void)
struct tpms_pcr_selection *sel = tpm20_pcr_selection->selections;
void *nsel, *end = (void*)tpm20_pcr_selection + tpm20_pcr_selection_size;

u32 count;
u32 count, numAlgs = 0;
for (count = 0; count < be32_to_cpu(tpm20_pcr_selection->count); count++) {
u8 sizeOfSelect = sel->sizeOfSelect;

nsel = (void*)sel + sizeof(*sel) + sizeOfSelect;
if (nsel > end)
break;

if (!sizeOfSelect || sel->pcrSelect[0] == 0) {
sel = nsel;
continue;
}

int hsize = tpm20_get_hash_buffersize(be16_to_cpu(sel->hashAlg));
if (hsize < 0) {
dprintf(DEBUG_tcg, "TPM is using an unsupported hash: %d\n",
Expand All @@ -282,13 +303,14 @@ tpm20_write_EfiSpecIdEventStruct(void)

int event_size = offsetof(struct TCG_EfiSpecIdEventStruct
, digestSizes[count+1]);
if (event_size > sizeof(event) - sizeof(u32)) {
if (event_size > sizeof(event) - sizeof(u8)) {
dprintf(DEBUG_tcg, "EfiSpecIdEventStruct pad too small\n");
return -1;
}

event.hdr.digestSizes[count].algorithmId = be16_to_cpu(sel->hashAlg);
event.hdr.digestSizes[count].digestSize = hsize;
event.hdr.digestSizes[numAlgs].algorithmId = be16_to_cpu(sel->hashAlg);
event.hdr.digestSizes[numAlgs].digestSize = hsize;
numAlgs++;

sel = nsel;
}
Expand All @@ -298,10 +320,10 @@ tpm20_write_EfiSpecIdEventStruct(void)
return -1;
}

event.hdr.numberOfAlgorithms = count;
event.hdr.numberOfAlgorithms = numAlgs;
int event_size = offsetof(struct TCG_EfiSpecIdEventStruct
, digestSizes[count]);
u32 *vendorInfoSize = (void*)&event + event_size;
, digestSizes[numAlgs]);
u8 *vendorInfoSize = (void*)&event + event_size;
*vendorInfoSize = 0;
event_size += sizeof(*vendorInfoSize);

Expand Down Expand Up @@ -336,14 +358,20 @@ tpm20_build_digest(struct tpm_log_entry *le, const u8 *sha1, int bigEndian)
void *nsel, *end = (void*)tpm20_pcr_selection + tpm20_pcr_selection_size;
void *dest = le->hdr.digest + sizeof(struct tpm2_digest_values);

u32 count;
u32 count, numAlgs = 0;
for (count = 0; count < be32_to_cpu(tpm20_pcr_selection->count); count++) {
u8 sizeOfSelect = sel->sizeOfSelect;

nsel = (void*)sel + sizeof(*sel) + sizeOfSelect;
if (nsel > end)
break;

/* PCR 0-7 unused? -- skip */
if (!sizeOfSelect || sel->pcrSelect[0] == 0) {
sel = nsel;
continue;
}

int hsize = tpm20_get_hash_buffersize(be16_to_cpu(sel->hashAlg));
if (hsize < 0) {
dprintf(DEBUG_tcg, "TPM is using an unsupported hash: %d\n",
Expand All @@ -368,6 +396,8 @@ tpm20_build_digest(struct tpm_log_entry *le, const u8 *sha1, int bigEndian)

dest += sizeof(*v) + hsize;
sel = nsel;

numAlgs++;
}

if (sel != end) {
Expand All @@ -377,9 +407,9 @@ tpm20_build_digest(struct tpm_log_entry *le, const u8 *sha1, int bigEndian)

struct tpm2_digest_values *v = (void*)le->hdr.digest;
if (bigEndian)
v->count = cpu_to_be32(count);
v->count = cpu_to_be32(numAlgs);
else
v->count = count;
v->count = numAlgs;

return dest - (void*)le->hdr.digest;
}
Expand Down Expand Up @@ -481,8 +511,17 @@ tpm20_get_pcrbanks(void)
if (ret)
return ret;

u32 size = be32_to_cpu(trg->hdr.totlen) -
offsetof(struct tpm2_res_getcapability, data);
/* defend against (broken) TPM sending packets that are too short */
u32 resplen = be32_to_cpu(trg->hdr.totlen);
if (resplen <= offsetof(struct tpm2_res_getcapability, data))
return -1;

u32 size = resplen - offsetof(struct tpm2_res_getcapability, data);
/* we need a valid tpml_pcr_selection up to and including sizeOfSelect */
if (size < offsetof(struct tpml_pcr_selection, selections) +
offsetof(struct tpms_pcr_selection, pcrSelect))
return -1;

tpm20_pcr_selection = malloc_high(size);
if (tpm20_pcr_selection) {
memcpy(tpm20_pcr_selection, &trg->data, size);
Expand Down Expand Up @@ -1920,6 +1959,9 @@ tpm20_clear(void)
dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_Clear = 0x%08x\n",
ret);

if (ret == 0)
printf("TPM2.0 clear success.\n");

return ret;
}

Expand Down
26 changes: 26 additions & 0 deletions src/util.h
Expand Up @@ -27,20 +27,34 @@ void boot_add_cd(struct drive_s *drive_g, const char *desc, int prio);
void boot_add_cbfs(void *data, const char *desc, int prio);
void interactive_bootmenu(void);
void bcv_prepboot(void);
u8 is_bootprio_strict(void);
struct pci_device;
int bootprio_find_pci_device(struct pci_device *pci);
int bootprio_find_mmio_device(void *mmio);
int bootprio_find_scsi_device(struct pci_device *pci, int target, int lun);
int bootprio_find_scsi_mmio_device(void *mmio, int target, int lun);
int bootprio_find_ata_device(struct pci_device *pci, int chanid, int slave);
int bootprio_find_fdc_device(struct pci_device *pci, int port, int fdid);
int bootprio_find_pci_rom(struct pci_device *pci, int instance);
int bootprio_find_named_rom(const char *name, int instance);
struct usbdevice_s;
int bootprio_find_usb(struct usbdevice_s *usbdev, int lun);
int get_keystroke_full(int msec);
int get_keystroke(int msec);
int find_pxen(void);
int find_usben(void);
int find_scon(void);
int find_com2en(void);
struct chs_s;
int boot_lchs_find_pci_device(struct pci_device *pci, struct chs_s *chs);
int boot_lchs_find_scsi_device(struct pci_device *pci, int target, int lun,
struct chs_s *chs);
int boot_lchs_find_ata_device(struct pci_device *pci, int chanid, int slave,
struct chs_s *chs);
int find_pxen(void);
int find_usben(void);
int find_scon(void);
int find_com2en(void);

// bootsplash.c
void enable_vga_console(void);
Expand Down Expand Up @@ -88,6 +102,17 @@ void display_uuid(void);
void copy_table(void *pos);
void smbios_setup(void);

// fw/dsdt_parser.c
struct acpi_device;
void acpi_dsdt_parse(void);
struct acpi_device *acpi_dsdt_find_string(struct acpi_device *prev, const char *hid);
struct acpi_device *acpi_dsdt_find_eisaid(struct acpi_device *prev, u16 eisaid);
char *acpi_dsdt_name(struct acpi_device *dev);
int acpi_dsdt_present_eisaid(u16 eisaid);
int acpi_dsdt_find_io(struct acpi_device *dev, u64 *min, u64 *max);
int acpi_dsdt_find_mem(struct acpi_device *dev, u64 *min, u64 *max);
int acpi_dsdt_find_irq(struct acpi_device *dev, u64 *irq);

// fw/coreboot.c
extern const char *CBvendor, *CBpart;
struct cbfs_file;
Expand Down Expand Up @@ -167,6 +192,7 @@ void sdcard_setup(void);
// hw/timer.c
void timer_setup(void);
void pmtimer_setup(u16 ioport);
void tsctimer_setfreq(u32 khz, const char *src);
u32 timer_calc(u32 msecs);
u32 timer_calc_usec(u32 usecs);
int timer_check(u32 end);
Expand Down
170 changes: 169 additions & 1 deletion vgasrc/atiext.c
Expand Up @@ -19,6 +19,9 @@
#define MM_DATA 0x0004
#define CRTC_GEN_CNTL 0x0050
#define CRTC_EXT_CNTL 0x0054
#define GPIO_VGA_DDC 0x0060
#define GPIO_DVI_DDC 0x0064
#define GPIO_MONID 0x0068
#define CRTC_H_TOTAL_DISP 0x0200
#define CRTC_V_TOTAL_DISP 0x0208
#define CRTC_OFFSET 0x0224
Expand All @@ -41,6 +44,12 @@
#define CRT_CRTC_ON 0x00008000

static u32 ati_io_addr VAR16 = 0;
static u32 ati_i2c_reg VAR16;
static u32 ati_i2c_bit_scl_out VAR16;
static u32 ati_i2c_bit_sda_out VAR16;
static u32 ati_i2c_bit_sda_in VAR16;
static u32 ati_i2c_bit_enable VAR16 = -1;


int
is_ati_mode(struct vgamode_s *vmode_g)
Expand Down Expand Up @@ -106,6 +115,20 @@ static inline void ati_write(u32 reg, u32 val)
}
}

static inline u32 ati_read(u32 reg)
{
u32 io_addr = GET_GLOBAL(ati_io_addr);
u32 val;

if (reg < 0x100) {
val = inl(io_addr + reg);
} else {
outl(reg, io_addr + MM_INDEX);
val = inl(io_addr + MM_DATA);
}
return val;
}

static void ati_clear(u32 offset, u32 size)
{
u8 data[64];
Expand Down Expand Up @@ -180,6 +203,141 @@ ati_set_mode(struct vgamode_s *vmode_g, int flags)
return stdvga_set_mode(vmode_g, flags);
}

/****************************************************************
* edid
****************************************************************/

static void
ati_i2c_set_scl_sda(int scl, int sda)
{
u32 enable = GET_GLOBAL(ati_i2c_bit_enable);
u32 data = 0;

if (enable != -1)
data |= (1 << enable);
if (!scl)
data |= (1 << GET_GLOBAL(ati_i2c_bit_scl_out));
if (!sda)
data |= (1 << GET_GLOBAL(ati_i2c_bit_sda_out));
ati_write(GET_GLOBAL(ati_i2c_reg), data);
}

static int
ati_i2c_get_sda(void)
{
u32 data = ati_read(GET_GLOBAL(ati_i2c_reg));

return data & (1 << GET_GLOBAL(ati_i2c_bit_sda_in)) ? 1 : 0;
}

static void ati_i2c_start(void)
{
ati_i2c_set_scl_sda(1, 1);
ati_i2c_set_scl_sda(1, 0);
ati_i2c_set_scl_sda(0, 0);
}

static void ati_i2c_ack(void)
{
ati_i2c_set_scl_sda(0, 0);
ati_i2c_set_scl_sda(1, 0);
ati_i2c_set_scl_sda(0, 0);
}

static void ati_i2c_stop(void)
{
ati_i2c_set_scl_sda(0, 0);
ati_i2c_set_scl_sda(1, 0);
ati_i2c_set_scl_sda(1, 1);
}

static void ati_i2c_send_byte(u8 byte)
{
int i, bit;

for (i = 0; i < 8; i++) {
bit = (1 << (7-i)) & byte ? 1 : 0;
ati_i2c_set_scl_sda(0, bit);
ati_i2c_set_scl_sda(1, bit);
ati_i2c_set_scl_sda(0, bit);
}
}

static u8 ati_i2c_recv_byte(void)
{
u8 byte = 0;
int i, bit;

for (i = 0; i < 8; i++) {
ati_i2c_set_scl_sda(0, 1);
ati_i2c_set_scl_sda(1, 1);
bit = ati_i2c_get_sda();
ati_i2c_set_scl_sda(0, 1);
if (bit)
byte |= (1 << (7-i));
}

return byte;
}

static void ati_i2c_edid(void)
{
u8 byte;
int i;

ati_i2c_start();
ati_i2c_send_byte(0x50 << 1 | 1);
ati_i2c_ack();
for (i = 0; i < 128; i++) {
byte = ati_i2c_recv_byte();
ati_i2c_ack();
SET_VGA(VBE_edid[i], byte);
}
ati_i2c_stop();
}

static void ati_i2c_edid_radeon(void)
{
int valid;

SET_VGA(ati_i2c_bit_scl_out, 17);
SET_VGA(ati_i2c_bit_sda_out, 16);
SET_VGA(ati_i2c_bit_sda_in, 8);

dprintf(1, "ati: reading edid blob (radeon vga) ... \n");
SET_VGA(ati_i2c_reg, GPIO_VGA_DDC);
ati_i2c_edid();
valid = (GET_GLOBAL(VBE_edid[0]) == 0x00 &&
GET_GLOBAL(VBE_edid[1]) == 0xff);
dprintf(1, "ati: ... %s\n", valid ? "good" : "invalid");
if (valid)
return;

dprintf(1, "ati: reading edid blob (radeon dvi) ... \n");
SET_VGA(ati_i2c_reg, GPIO_DVI_DDC);
ati_i2c_edid();
valid = (GET_GLOBAL(VBE_edid[0]) == 0x00 &&
GET_GLOBAL(VBE_edid[1]) == 0xff);
dprintf(1, "ati: ... %s\n", valid ? "good" : "invalid");
}

static void ati_i2c_edid_rage128(void)
{
int valid;

SET_VGA(ati_i2c_bit_enable, 25);
SET_VGA(ati_i2c_bit_scl_out, 18);
SET_VGA(ati_i2c_bit_sda_out, 17);
SET_VGA(ati_i2c_bit_sda_in, 9);
SET_VGA(ati_i2c_reg, GPIO_MONID);

dprintf(1, "ati: reading edid blob (rage128) ... \n");
ati_i2c_edid();
valid = (GET_GLOBAL(VBE_edid[0]) == 0x00 &&
GET_GLOBAL(VBE_edid[1]) == 0xff);
dprintf(1, "ati: ... %s\n", valid ? "good" : "invalid");
}

/****************************************************************
* init
****************************************************************/
Expand Down Expand Up @@ -236,10 +394,20 @@ ati_setup(void)
height > 0xfff ||
mem > totalmem ||
memmodel != MM_DIRECT) {
dprintf(1, "ati: removing mode 0x%x\n", GET_GLOBAL(m->mode));
dprintf(3, "ati: removing mode 0x%x\n", GET_GLOBAL(m->mode));
SET_VGA(m->mode, 0xffff);
}
}

u16 device = pci_config_readw(bdf, PCI_DEVICE_ID);
switch (device) {
case 0x5046:
ati_i2c_edid_rage128();
break;
case 0x5159:
ati_i2c_edid_radeon();
break;
}

return 0;
}
38 changes: 29 additions & 9 deletions vgasrc/bochsdisplay.c
@@ -1,16 +1,21 @@
// Simple framebuffer vgabios for use with qemu bochs-display device
//
// Copyright (C) 2019 Gerd Hoffmann <kraxel@redhat.com>
//
// This file may be distributed under the terms of the GNU LGPLv3 license.

#include "biosvar.h" // GET_BDA
#include "output.h" // dprintf
#include "string.h" // memset16_far
#include "bochsvga.h" // VBE_BOCHS_*
#include "hw/pci.h" // pci_config_readl
#include "hw/pci_regs.h" // PCI_BASE_ADDRESS_0
#include "vgabios.h" // SET_VGA
#include "vgautil.h" // VBE_total_memory

#define FRAMEBUFFER_WIDTH 1024
#define FRAMEBUFFER_HEIGHT 768
#define FRAMEBUFFER_BPP 4
#define FRAMEBUFFER_STRIDE (FRAMEBUFFER_BPP * FRAMEBUFFER_WIDTH)
#define FRAMEBUFFER_SIZE (FRAMEBUFFER_STRIDE * FRAMEBUFFER_HEIGHT)

int
bochs_display_setup(void)
Expand Down Expand Up @@ -40,16 +45,31 @@ bochs_display_setup(void)
if (id != VBE_DISPI_ID5)
return -1;

dprintf(1, "bochs-display: using %dx%d, %d bpp (%d stride)\n"
, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT
, FRAMEBUFFER_BPP * 8, FRAMEBUFFER_STRIDE);
int i;
u8 *edid = (void*)(io_addr);
for (i = 0; i < sizeof(VBE_edid); i++)
SET_VGA(VBE_edid[i], readb(edid + i));

int fb_width = FRAMEBUFFER_WIDTH;
int fb_height = FRAMEBUFFER_HEIGHT;
if (GET_GLOBAL(VBE_edid[0]) == 0x00 &&
GET_GLOBAL(VBE_edid[1]) == 0xff) {
fb_width = GET_GLOBAL(VBE_edid[54 + 2]);
fb_width |= (GET_GLOBAL(VBE_edid[54 + 4]) & 0xf0) << 4;
fb_height = GET_GLOBAL(VBE_edid[54 + 5]);
fb_height |= (GET_GLOBAL(VBE_edid[54 + 7]) & 0xf0) << 4;
}
int fb_stride = FRAMEBUFFER_BPP * fb_width;

dprintf(1, "bochs-display: using %dx%d, %d bpp (%d stride)\n"
, fb_width, fb_height
, FRAMEBUFFER_BPP * 8, fb_stride);

cbvga_setup_modes(lfb_addr, FRAMEBUFFER_BPP * 8,
FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT,
FRAMEBUFFER_STRIDE);
fb_width, fb_height, fb_stride);

writew(dispi + VBE_DISPI_INDEX_XRES, FRAMEBUFFER_WIDTH);
writew(dispi + VBE_DISPI_INDEX_YRES, FRAMEBUFFER_HEIGHT);
writew(dispi + VBE_DISPI_INDEX_XRES, fb_width);
writew(dispi + VBE_DISPI_INDEX_YRES, fb_height);
writew(dispi + VBE_DISPI_INDEX_BPP, FRAMEBUFFER_BPP * 8);
writew(dispi + VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED);

Expand Down
19 changes: 16 additions & 3 deletions vgasrc/bochsvga.c
Expand Up @@ -325,19 +325,25 @@ bochsvga_setup(void)
return 0;

u32 lfb_addr = VBE_DISPI_LFB_PHYSICAL_ADDRESS;
u32 io_addr = 0;
int bdf = GET_GLOBAL(VgaBDF);
if (CONFIG_VGA_PCI && bdf >= 0) {
u16 vendor = pci_config_readw(bdf, PCI_VENDOR_ID);
int barid;
int barid, bar;
switch (vendor) {
case 0x15ad: /* qemu vmware vga */
barid = 1;
break;
default: /* stdvga, qxl, virtio */
case 0x1234: /* stdvga */
bar = pci_config_readl(bdf, PCI_BASE_ADDRESS_2);
io_addr = bar & PCI_BASE_ADDRESS_IO_MASK;
barid = 0;
break;
default: /* qxl, virtio */
barid = 0;
break;
}
u32 bar = pci_config_readl(bdf, PCI_BASE_ADDRESS_0 + barid * 4);
bar = pci_config_readl(bdf, PCI_BASE_ADDRESS_0 + barid * 4);
lfb_addr = bar & PCI_BASE_ADDRESS_MEM_MASK;
dprintf(1, "VBE DISPI: bdf %02x:%02x.%x, bar %d\n", pci_bdf_to_bus(bdf)
, pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf), barid);
Expand Down Expand Up @@ -373,5 +379,12 @@ bochsvga_setup(void)
}
}

if (io_addr) {
int i;
u8 *edid = (void*)(io_addr);
for (i = 0; i < sizeof(VBE_edid); i++)
SET_VGA(VBE_edid[i], readb(edid + i));
}

return 0;
}
80 changes: 9 additions & 71 deletions vgasrc/cbvga.c
Expand Up @@ -13,76 +13,13 @@
#include "vgabios.h" // SET_VGA
#include "vgafb.h" // handle_gfx_op
#include "vgautil.h" // VBE_total_memory
#include "svgamodes.h" // svga_modes

static int CBmode VAR16;
static struct vgamode_s CBmodeinfo VAR16;
static struct vgamode_s CBemulinfo VAR16;
static u32 CBlinelength VAR16;

static struct cbvga_mode_s
{
u16 mode;
struct vgamode_s info;
} cbvesa_modes[] VAR16 = {
/* VESA 1.0 modes */
{ 0x110, { MM_DIRECT, 640, 480, 15, 8, 16, SEG_GRAPH } },
{ 0x111, { MM_DIRECT, 640, 480, 16, 8, 16, SEG_GRAPH } },
{ 0x112, { MM_DIRECT, 640, 480, 24, 8, 16, SEG_GRAPH } },
{ 0x113, { MM_DIRECT, 800, 600, 15, 8, 16, SEG_GRAPH } },
{ 0x114, { MM_DIRECT, 800, 600, 16, 8, 16, SEG_GRAPH } },
{ 0x115, { MM_DIRECT, 800, 600, 24, 8, 16, SEG_GRAPH } },
{ 0x116, { MM_DIRECT, 1024, 768, 15, 8, 16, SEG_GRAPH } },
{ 0x117, { MM_DIRECT, 1024, 768, 16, 8, 16, SEG_GRAPH } },
{ 0x118, { MM_DIRECT, 1024, 768, 24, 8, 16, SEG_GRAPH } },
{ 0x119, { MM_DIRECT, 1280, 1024, 15, 8, 16, SEG_GRAPH } },
{ 0x11A, { MM_DIRECT, 1280, 1024, 16, 8, 16, SEG_GRAPH } },
{ 0x11B, { MM_DIRECT, 1280, 1024, 24, 8, 16, SEG_GRAPH } },
{ 0x11D, { MM_DIRECT, 1600, 1200, 15, 8, 16, SEG_GRAPH } },
{ 0x11E, { MM_DIRECT, 1600, 1200, 16, 8, 16, SEG_GRAPH } },
{ 0x11F, { MM_DIRECT, 1600, 1200, 24, 8, 16, SEG_GRAPH } },
/* VESA 2.0 modes */
{ 0x141, { MM_DIRECT, 640, 400, 32, 8, 16, SEG_GRAPH } },
{ 0x142, { MM_DIRECT, 640, 480, 32, 8, 16, SEG_GRAPH } },
{ 0x143, { MM_DIRECT, 800, 600, 32, 8, 16, SEG_GRAPH } },
{ 0x144, { MM_DIRECT, 1024, 768, 32, 8, 16, SEG_GRAPH } },
{ 0x145, { MM_DIRECT, 1280, 1024, 32, 8, 16, SEG_GRAPH } },
{ 0x147, { MM_DIRECT, 1600, 1200, 32, 8, 16, SEG_GRAPH } },
{ 0x149, { MM_DIRECT, 1152, 864, 15, 8, 16, SEG_GRAPH } },
{ 0x14a, { MM_DIRECT, 1152, 864, 16, 8, 16, SEG_GRAPH } },
{ 0x14b, { MM_DIRECT, 1152, 864, 24, 8, 16, SEG_GRAPH } },
{ 0x14c, { MM_DIRECT, 1152, 864, 32, 8, 16, SEG_GRAPH } },
{ 0x175, { MM_DIRECT, 1280, 768, 16, 8, 16, SEG_GRAPH } },
{ 0x176, { MM_DIRECT, 1280, 768, 24, 8, 16, SEG_GRAPH } },
{ 0x177, { MM_DIRECT, 1280, 768, 32, 8, 16, SEG_GRAPH } },
{ 0x178, { MM_DIRECT, 1280, 800, 16, 8, 16, SEG_GRAPH } },
{ 0x179, { MM_DIRECT, 1280, 800, 24, 8, 16, SEG_GRAPH } },
{ 0x17a, { MM_DIRECT, 1280, 800, 32, 8, 16, SEG_GRAPH } },
{ 0x17b, { MM_DIRECT, 1280, 960, 16, 8, 16, SEG_GRAPH } },
{ 0x17c, { MM_DIRECT, 1280, 960, 24, 8, 16, SEG_GRAPH } },
{ 0x17d, { MM_DIRECT, 1280, 960, 32, 8, 16, SEG_GRAPH } },
{ 0x17e, { MM_DIRECT, 1440, 900, 16, 8, 16, SEG_GRAPH } },
{ 0x17f, { MM_DIRECT, 1440, 900, 24, 8, 16, SEG_GRAPH } },
{ 0x180, { MM_DIRECT, 1440, 900, 32, 8, 16, SEG_GRAPH } },
{ 0x181, { MM_DIRECT, 1400, 1050, 16, 8, 16, SEG_GRAPH } },
{ 0x182, { MM_DIRECT, 1400, 1050, 24, 8, 16, SEG_GRAPH } },
{ 0x183, { MM_DIRECT, 1400, 1050, 32, 8, 16, SEG_GRAPH } },
{ 0x184, { MM_DIRECT, 1680, 1050, 16, 8, 16, SEG_GRAPH } },
{ 0x185, { MM_DIRECT, 1680, 1050, 24, 8, 16, SEG_GRAPH } },
{ 0x186, { MM_DIRECT, 1680, 1050, 32, 8, 16, SEG_GRAPH } },
{ 0x187, { MM_DIRECT, 1920, 1200, 16, 8, 16, SEG_GRAPH } },
{ 0x188, { MM_DIRECT, 1920, 1200, 24, 8, 16, SEG_GRAPH } },
{ 0x189, { MM_DIRECT, 1920, 1200, 32, 8, 16, SEG_GRAPH } },
{ 0x18a, { MM_DIRECT, 2560, 1600, 16, 8, 16, SEG_GRAPH } },
{ 0x18b, { MM_DIRECT, 2560, 1600, 24, 8, 16, SEG_GRAPH } },
{ 0x18c, { MM_DIRECT, 2560, 1600, 32, 8, 16, SEG_GRAPH } },
{ 0x18d, { MM_DIRECT, 1280, 720, 16, 8, 16, SEG_GRAPH } },
{ 0x18e, { MM_DIRECT, 1280, 720, 24, 8, 16, SEG_GRAPH } },
{ 0x18f, { MM_DIRECT, 1280, 720, 32, 8, 16, SEG_GRAPH } },
{ 0x190, { MM_DIRECT, 1920, 1080, 16, 8, 16, SEG_GRAPH } },
{ 0x191, { MM_DIRECT, 1920, 1080, 24, 8, 16, SEG_GRAPH } },
{ 0x192, { MM_DIRECT, 1920, 1080, 32, 8, 16, SEG_GRAPH } },
};

struct vgamode_s *cbvga_find_mode(int mode)
{
if (mode == GET_GLOBAL(CBmode))
Expand All @@ -91,8 +28,8 @@ struct vgamode_s *cbvga_find_mode(int mode)
return &CBemulinfo;

int i;
for (i = 0; i < ARRAY_SIZE(cbvesa_modes); i++) {
struct cbvga_mode_s *cbmode_g = &cbvesa_modes[i];
for (i = 0; i < GET_GLOBAL(svga_mcount); i++) {
struct generic_svga_mode *cbmode_g = &svga_modes[i];
if (GET_GLOBAL(cbmode_g->mode) == 0xffff)
continue;
if (GET_GLOBAL(cbmode_g->mode) == mode)
Expand All @@ -114,8 +51,8 @@ cbvga_list_modes(u16 seg, u16 *dest, u16 *last)
* + 24 Bpp and 32 Bpp are supported
*/
int i;
for (i = 0; i < ARRAY_SIZE(cbvesa_modes) && dest < last; i++) {
struct cbvga_mode_s *cbmode_g = &cbvesa_modes[i];
for (i = 0; i < GET_GLOBAL(svga_mcount) && dest < last; i++) {
struct generic_svga_mode *cbmode_g = &svga_modes[i];
u16 mode = GET_GLOBAL(cbmode_g->mode);
if (mode == 0xffff)
continue;
Expand Down Expand Up @@ -265,10 +202,11 @@ cbvga_setup_modes(u64 addr, u8 bpp, u32 xlines, u32 ylines, u32 linelength)
, get_global_seg(), &CBmodeinfo, sizeof(CBemulinfo));

// Validate modes
for (i = 0; i < ARRAY_SIZE(cbvesa_modes); i++) {
struct cbvga_mode_s *cbmode_g = &cbvesa_modes[i];
for (i = 0; i < GET_GLOBAL(svga_mcount); i++) {
struct generic_svga_mode *cbmode_g = &svga_modes[i];
/* Skip VBE modes that doesn't fit into coreboot's framebuffer */
if ((GET_GLOBAL(cbmode_g->info.height) > ylines)
if ((GET_GLOBAL(cbmode_g->info.memmodel) != MM_DIRECT)
|| (GET_GLOBAL(cbmode_g->info.height) > ylines)
|| (GET_GLOBAL(cbmode_g->info.width) > xlines)
|| (GET_GLOBAL(cbmode_g->info.depth) != bpp)) {
dprintf(3, "Removing mode %x\n", GET_GLOBAL(cbmode_g->mode));
Expand Down
6 changes: 6 additions & 0 deletions vgasrc/ramfb.c
@@ -1,3 +1,9 @@
// Simple framebuffer vgabios for use with qemu ramfb device
//
// Copyright (C) 2019 Gerd Hoffmann <kraxel@redhat.com>
//
// This file may be distributed under the terms of the GNU LGPLv3 license.

#include "biosvar.h" // GET_BDA
#include "output.h" // dprintf
#include "string.h" // memset16_far
Expand Down
16 changes: 16 additions & 0 deletions vgasrc/svgamodes.c
@@ -1,3 +1,11 @@
// Common svga mode definitions
//
// Copyright (C) 2012 Kevin O'Connor <kevin@koconnor.net>
// Copyright (C) 2011 Julian Pidancet <julian.pidancet@citrix.com>
// Copyright (C) 2002 Jeroen Janssen
//
// This file may be distributed under the terms of the GNU LGPLv3 license.

#include "stdvga.h" // SEG_GRAPH
#include "vgabios.h" // VAR16

Expand Down Expand Up @@ -76,5 +84,13 @@ struct generic_svga_mode svga_modes[] VAR16 = {
{ 0x190, { MM_DIRECT, 1920, 1080, 16, 8, 16, SEG_GRAPH } },
{ 0x191, { MM_DIRECT, 1920, 1080, 24, 8, 16, SEG_GRAPH } },
{ 0x192, { MM_DIRECT, 1920, 1080, 32, 8, 16, SEG_GRAPH } },

/* custom resolutions for 16:9 displays */
{ 0x193, { MM_DIRECT, 1600, 900, 16, 8, 16, SEG_GRAPH } },
{ 0x194, { MM_DIRECT, 1600, 900, 24, 8, 16, SEG_GRAPH } },
{ 0x195, { MM_DIRECT, 1600, 900, 32, 8, 16, SEG_GRAPH } },
{ 0x196, { MM_DIRECT, 2560, 1440, 16, 8, 16, SEG_GRAPH } },
{ 0x197, { MM_DIRECT, 2560, 1440, 24, 8, 16, SEG_GRAPH } },
{ 0x198, { MM_DIRECT, 2560, 1440, 32, 8, 16, SEG_GRAPH } },
};
unsigned int svga_mcount VAR16 = ARRAY_SIZE(svga_modes);
30 changes: 30 additions & 0 deletions vgasrc/vbe.c
Expand Up @@ -25,6 +25,7 @@ u32 VBE_total_memory VAR16 = 256 * 1024;
u32 VBE_capabilities VAR16;
u32 VBE_framebuffer VAR16;
u16 VBE_win_granularity VAR16;
u8 VBE_edid[256] VAR16;

static void
vbe_104f00(struct bregs *regs)
Expand Down Expand Up @@ -400,6 +401,34 @@ vbe_104f10(struct bregs *regs)
regs->ax = 0x004f;
}

static void
vbe_104f15(struct bregs *regs)
{
int offset;

switch (regs->bl) {
case 0x00:
if (GET_GLOBAL(VBE_edid[0]) != 0x00 ||
GET_GLOBAL(VBE_edid[1]) != 0xff)
goto err;
regs->bx = 0x0103;
break;
case 0x01:
offset = regs->dx * 128;
if (offset >= sizeof(VBE_edid))
goto err;
memcpy_far(regs->es, (void*)(regs->di+0),
get_global_seg(), VBE_edid + offset,
128);
break;
err:
default:
regs->ax = 0x014f;
return;
}
regs->ax = 0x004f;
}

static void
vbe_104fXX(struct bregs *regs)
{
Expand Down Expand Up @@ -427,6 +456,7 @@ handle_104f(struct bregs *regs)
case 0x08: vbe_104f08(regs); break;
case 0x0a: vbe_104f0a(regs); break;
case 0x10: vbe_104f10(regs); break;
case 0x15: vbe_104f15(regs); break;
default: vbe_104fXX(regs); break;
}
}
7 changes: 3 additions & 4 deletions vgasrc/vgabios.c
Expand Up @@ -336,6 +336,9 @@ static void
handle_1000(struct bregs *regs)
{
int mode = regs->al & 0x7f;
int flags = MF_LEGACY | (GET_BDA(modeset_ctl) & (MF_NOPALETTE|MF_GRAYSUM));
if (regs->al & 0x80)
flags |= MF_NOCLEARMEM;

// Set regs->al
if (mode > 7)
Expand All @@ -345,10 +348,6 @@ handle_1000(struct bregs *regs)
else
regs->al = 0x30;

int flags = MF_LEGACY | (GET_BDA(modeset_ctl) & (MF_NOPALETTE|MF_GRAYSUM));
if (regs->al & 0x80)
flags |= MF_NOCLEARMEM;

vga_set_mode(mode, flags);
}

Expand Down
2 changes: 1 addition & 1 deletion vgasrc/vgahw.h
Expand Up @@ -36,7 +36,7 @@ static inline int vgahw_set_mode(struct vgamode_s *vmode_g, int flags) {
static inline void vgahw_list_modes(u16 seg, u16 *dest, u16 *last) {
if (CONFIG_VGA_CIRRUS)
clext_list_modes(seg, dest, last);
if (CONFIG_VGA_ATI)
else if (CONFIG_VGA_ATI)
ati_list_modes(seg, dest, last);
else if (CONFIG_VGA_BOCHS)
bochsvga_list_modes(seg, dest, last);
Expand Down
1 change: 1 addition & 0 deletions vgasrc/vgautil.h
Expand Up @@ -89,6 +89,7 @@ extern u32 VBE_total_memory;
extern u32 VBE_capabilities;
extern u32 VBE_framebuffer;
extern u16 VBE_win_granularity;
extern u8 VBE_edid[256];
void handle_104f(struct bregs *regs);

// vgafonts.c
Expand Down