0391d0b023
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>
104 lines
2.3 KiB
C
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;
|
|
}
|