coreboot-kgpe-d16/util/intelmetool/rcba.c
Patrick Rudolph 0391d0b023 util/intelmetool: Add support for platforms without RCBA
Only try to unhide MEI if the PCI device wasn't found and
probe for RCBA before trying to use it.

Allows to run the utility on Skylake and newer hardware that
do not have RCBA any more.

TODO: Use sideband interface to unhide MEI.

Change-Id: I7926aa80b132d5be9fece0724516701d74dd4d3d
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Reviewed-on: https://review.coreboot.org/25399
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com>
2018-04-16 22:27:02 +00:00

104 lines
2.3 KiB
C

/*
* Copyright (C) 2014 Damien Zammit <damien@zamaudio.com>
* Copyright (C) 2017 Patrick Rudolph <siro@das-labor.org>
*
* 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.
*/
#include <stdio.h>
#include <inttypes.h>
#include "intelmetool.h"
#include "mmap.h"
#include "rcba.h"
static const int size = 0x4000;
/* Returns the physical RCBA base address or zero on error. */
u32 get_rcba_phys(void)
{
struct pci_access *pacc;
struct pci_dev *sb;
uint32_t rcba_phys;
pacc = pci_alloc();
pacc->method = PCI_ACCESS_I386_TYPE1;
pci_init(pacc);
pci_scan_bus(pacc);
sb = pci_get_dev(pacc, 0, 0, 0x1f, 0);
if (!sb) {
printf("Uh oh, southbridge not on BDF(0:31:0), please report "
"this error, exiting.\n");
pci_cleanup(pacc);
return 0;
}
pci_fill_info(sb, PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_SIZES |
PCI_FILL_CLASS);
rcba_phys = pci_read_long(sb, 0xf0) & 0xfffffffe;
pci_free_dev(sb);
pci_cleanup(pacc);
return rcba_phys;
}
/*
* Writes 'val' to RCBA register at address 'addr'.
* Returns 1 on error and 0 on success.
*/
int write_rcba32(uint32_t addr, uint32_t val)
{
volatile uint8_t *rcba;
const uint32_t rcba_phys = get_rcba_phys();
if (!rcba_phys) {
printf("Could not get RCBA address\n");
return 1;
}
rcba = map_physical((off_t)rcba_phys, size);
if (rcba == NULL) {
printf("Could not map RCBA\n");
return 1;
}
*(uint32_t *)(rcba + addr) = val;
munmap((void *)rcba, size);
return 0;
}
/*
* Reads RCBA register at address 'addr' and stores it in 'val'.
* Returns 1 on error and 0 on success.
*/
int read_rcba32(uint32_t addr, uint32_t *val)
{
volatile uint8_t *rcba;
const uint32_t rcba_phys = get_rcba_phys();
if (!rcba_phys) {
printf("Could not get RCBA address\n");
return 1;
}
rcba = map_physical((off_t)rcba_phys, size);
if (rcba == NULL) {
printf("Could not map RCBA\n");
return 1;
}
*val = *(uint32_t *)(rcba + addr);
munmap((void *)rcba, size);
return 0;
}