hackedteam/vector-edk

View on GitHub
AppPkg/Applications/chipsec/mmio.c

Summary

Maintainability
Test Coverage
#include <Uefi.h>
#include <stdio.h>

#include "config.h"
#include "driver.h"
#include "pci.h"

BOOLEAN is_MMIO_BAR_defined(CONFIGURATION *Platform, CHAR8* BarName)
{
    if (get_BAR(Platform, BarName) != NULL)
        return TRUE;

    return FALSE;
}

EFI_STATUS get_MMIO_BAR_base_address(BAR *bar, UINT64 *base, unsigned int *size)
{
    UINT32 base_lo, base_hi;

    *base = (UINT64) -1;
    *size = (UINTN) -1;

    if (bar->Width == 8)
    {
        base_lo = pci_read_dword(bar->Bus, bar->Dev, bar->Fun, bar->Reg);
        base_hi = pci_read_dword(bar->Bus, bar->Dev, bar->Fun, bar->Reg + 4);

        *base = base_hi;
        *base <<= 32;
        *base |= base_lo;

        printf("[MMIO!get_MMIO_BAR_base_address] Width 8 (hi) %x (lo) %x\n", base_hi, base_lo);
    }
    else
    {
        *base = 0;
        *base = pci_read_dword(bar->Bus, bar->Dev, bar->Fun, bar->Reg);
        printf("[MMIO!get_MMIO_BAR_base_address] Width 4 %x\n", *base);
    }

    if (bar->EnableBit != 0)
    {
        //UINT8 en_mask = 1 << bar->EnableBit;

        //if (*base == 0 && en_mask) 
    }

    if (bar->Mask != 0)
        *base &= bar->Mask;

    if (bar->Offset != 0)
        *base = *base + bar->Offset;

    if (bar->Size == 0)
        *size = 0x1000;
    else
        *size = bar->Size;

    printf("[MMIO!-> %x %x", *base, *size);

    return RETURN_SUCCESS;
}

BOOLEAN is_MMIO_BAR_enabled(BAR *bar)
{
    UINT64 base;
    unsigned int size;

    get_MMIO_BAR_base_address(bar, &base, &size);
    
    if (bar->EnableBit != 0)
    {
        UINT8 en_mask = 1 << bar->EnableBit;

        return ((base != 0) & en_mask);
    }

    return TRUE;
}

BOOLEAN is_MMIO_BAR_programmed(BAR *bar)
{
    UINT64 base;
    unsigned int size;

    get_MMIO_BAR_base_address(bar, &base, &size);

    return (base != 0) ? TRUE : FALSE;
}

VOID write_MMIO_reg(UINTN bar_base, UINTN offset, UINTN value)
{
    memcpy((UINT8*) bar_base + offset, &value, 4);    // dword!
}

UINTN read_MMIO_reg(UINTN bar_base, UINTN offset)
{
    UINTN value;

    value = 0;

    memcpy(&value, (UINT8*) (bar_base + offset), 4);

    return value;
}

UINTN read_MMIO_BAR_reg(BAR *bar, UINTN offset)
{
    UINT64 bar_base;

    UINTN result;
    unsigned int bar_size;

    get_MMIO_BAR_base_address(bar, &bar_base, &bar_size);

    return read_MMIO_reg((UINTN) bar_base, offset);
}

VOID write_MMIO_BAR_reg(BAR *bar, UINTN offset, UINTN value)
{
    UINT64 bar_base;
    UINTN result;
    unsigned int bar_size;

    get_MMIO_BAR_base_address(bar, &bar_base, &bar_size);

    write_MMIO_reg((UINTN) bar_base, offset, value);
}

VOID read_MMIO(UINTN bar_base, UINTN size, UINT8 *buffer)
{
    UINT32 *regs = (UINT32 *) buffer;
    UINT32 r = 0;

    while(r < size)
    {
        regs[r / 4] = (UINT32) read_MMIO_reg(bar_base, r);

        r += 4;
    }
}

UINTN get_MMCFG_base_address(CONFIGURATION *Configuration)
{
    UINT64 bar_address;
    unsigned int bar_size;

    BAR *mmcfg = get_BAR(Configuration, "MMCFG");

    get_MMIO_BAR_base_address(mmcfg, &bar_address, &bar_size);

    if (PCI_PCIEXBAR_REG_LENGTH_256MB == (bar_address & PCI_PCIEXBAR_REG_LENGTH_MASK) >> 1)
    {
        bar_address &= ~ (PCI_PCIEXBAR_REG_ADMSK128 | PCI_PCIEXBAR_REG_ADMSK64);
    }
    else if (PCI_PCIEXBAR_REG_LENGTH_128MB == (bar_address & PCI_PCIEXBAR_REG_LENGTH_MASK) >> 1)
    {
        bar_address &= ~PCI_PCIEXBAR_REG_ADMSK64;
    }

    return (UINTN) bar_address;

}

UINTN read_MMCFG_reg(CONFIGURATION *Configuration, UINT16 bus, UINT16 dev, UINT16 fun, UINT16 off, UINT16 size)
{
    UINTN bar_address, bar_address_off;
    UINTN value;

    bar_address = get_MMCFG_base_address(Configuration);
    bar_address_off = (bus * 32 * 8 + dev * 8 + fun) * 0x1000 + off;

    value = read_MMIO_reg(bar_address, bar_address_off);

    if (size == 1)
        value &= 0xff;
    else if (size == 2)
        value &= 0xffff;
    
    return value;
}


VOID write_MMCFG_reg(CONFIGURATION *Configuration, UINT16 bus, UINT16 dev, UINT16 fun, UINT16 off, UINT32 value)
{
    UINTN bar_address, bar_address_off;

    bar_address = get_MMCFG_base_address(Configuration);
    bar_address_off = (bus * 32 * 8 + dev * 8 + fun) * 0x1000 + off;

    write_MMIO_reg(bar_address, bar_address_off, value);
}

UINTN read_register(CONFIGURATION *Configuration, CHAR8 *reg_name)
{
    REGISTER *reg;
    UINTN Result;

    reg = get_BAR_reg(Configuration, reg_name);

    Result = 0;

    if (reg->Type == PCICFG)
    {
        Result = ReadPCICfg(reg->Bus, reg->Dev, reg->Fun, reg->Offset, reg->Size);
        //printf("\n[ReadPCICfg] (%x:%x:%x:%x:%x) = %x", reg->Bus, reg->Dev, reg->Fun, reg->Offset, reg->Size, Result); 
    }
    else
    {
        // none!
    }

    return Result;
}

VOID write_register(CONFIGURATION *Configuration, CHAR8 *reg_name, UINTN value)
{
    REGISTER *reg;

    reg = get_BAR_reg(Configuration, reg_name);

    if (reg->Type == PCICFG)
    {
        //printf("\n[write_register] %s %x", reg_name, value);
        WritePCICfg(reg->Bus, reg->Dev, reg->Fun, reg->Offset, reg->Size, value);
    }
    else
    {
        // none!
    }

    return;
}