ifdtool: port the feature to set AltMeDisable/HAP bit here
Port the newest feature of me_cleaner to ifdtool (https://github.com/corna/me_cleaner/ , Discussed in https://github.com/corna/me_cleaner/issues/53 ) to set AltMeDisable (or HAP for skylake/ME11) bit to the IFD to disable ME. In this commit I use (ifd_version >= IFD_VERSION_2) to judge whether HAP instead AltMeDisable should be set, since this condition is only fulfilled on skylake or newer platforms. This feature needs to guess ich revision, which needs guess_ich_chipset() from flashrom to be ported here. Routines to dump those bits are also added. Change-Id: I9a2ecc60cfbb9ee9d96f15be3d53226cb428729a Signed-off-by: Bill XIE <persmule@gmail.com> Reviewed-on: https://review.coreboot.org/21437 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Patrick Georgi <pgeorgi@google.com>
This commit is contained in:
parent
cea31ea5eb
commit
b3e15a2895
|
@ -40,6 +40,7 @@
|
|||
(const char *)&(ptr)[1] <= (base) + (limit))
|
||||
|
||||
static int ifd_version;
|
||||
static int chipset;
|
||||
static unsigned int max_regions = 0;
|
||||
static int selected_chip = 0;
|
||||
static int platform = -1;
|
||||
|
@ -56,6 +57,33 @@ static const struct region_name region_names[MAX_REGIONS] = {
|
|||
{ "EC", "ec", "flashregion_8_ec.bin" },
|
||||
};
|
||||
|
||||
/* port from flashrom */
|
||||
static const char *const ich_chipset_names[] = {
|
||||
"Unknown ICH",
|
||||
"ICH",
|
||||
"ICH2345",
|
||||
"ICH6",
|
||||
"SCH U",
|
||||
"Atom E6xx",
|
||||
"Atom S1220 S1240 S1260",
|
||||
"ICH7",
|
||||
"ICH8",
|
||||
"ICH9",
|
||||
"ICH10",
|
||||
"5 series Ibex Peak",
|
||||
"6 series Cougar Point",
|
||||
"7 series Panther Point",
|
||||
"8 series Lynx Point",
|
||||
"Baytrail",
|
||||
"8 series Lynx Point LP",
|
||||
"8 series Wellsburg",
|
||||
"9 series Wildcat Point",
|
||||
"9 series Wildcat Point LP",
|
||||
"100 series Sunrise Point",
|
||||
"C620 series Lewisburg",
|
||||
NULL
|
||||
};
|
||||
|
||||
static fdbar_t *find_fd(char *image, int size)
|
||||
{
|
||||
int i, found = 0;
|
||||
|
@ -140,6 +168,41 @@ static fmsba_t *find_fmsba(char *image, int size)
|
|||
return PTR_IN_RANGE(fmsba, image, size) ? fmsba : NULL;
|
||||
}
|
||||
|
||||
/* port from flashrom */
|
||||
static enum ich_chipset guess_ich_chipset(const fdbar_t *fdb)
|
||||
{
|
||||
uint32_t iccriba = (fdb->flmap2 >> 16) & 0xff;
|
||||
uint32_t msl = (fdb->flmap2 >> 8) & 0xff;
|
||||
uint32_t isl = (fdb->flmap1 >> 24);
|
||||
uint32_t nm = (fdb->flmap1 >> 8) & 0x7;
|
||||
|
||||
if (iccriba == 0x00) {
|
||||
if (msl == 0 && isl <= 2)
|
||||
return CHIPSET_ICH8;
|
||||
else if (isl <= 2)
|
||||
return CHIPSET_ICH9;
|
||||
else if (isl <= 10)
|
||||
return CHIPSET_ICH10;
|
||||
else if (isl <= 16)
|
||||
return CHIPSET_5_SERIES_IBEX_PEAK;
|
||||
printf("Peculiar firmware descriptor, assuming Ibex Peak compatibility.\n");
|
||||
return CHIPSET_5_SERIES_IBEX_PEAK;
|
||||
} else if (iccriba < 0x31 && (fdb->flmap2 & 0xff) < 0x30) {
|
||||
if (msl == 0 && isl <= 17)
|
||||
return CHIPSET_BAYTRAIL;
|
||||
else if (msl <= 1 && isl <= 18)
|
||||
return CHIPSET_6_SERIES_COUGAR_POINT;
|
||||
else if (msl <= 1 && isl <= 21)
|
||||
return CHIPSET_8_SERIES_LYNX_POINT;
|
||||
printf("Peculiar firmware descriptor, assuming Wildcat Point compatibility.\n");
|
||||
return CHIPSET_9_SERIES_WILDCAT_POINT;
|
||||
} else if (nm == 6) {
|
||||
return CHIPSET_C620_SERIES_LEWISBURG;
|
||||
} else {
|
||||
return CHIPSET_100_SERIES_SUNRISE_POINT;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Some newer platforms have re-defined the FCBA field that was used to
|
||||
* distinguish IFD v1 v/s v2. Define a list of platforms that we know do not
|
||||
|
@ -171,9 +234,14 @@ static int get_ifd_version_from_fcba(char *image, int size)
|
|||
{
|
||||
int read_freq;
|
||||
const fcba_t *fcba = find_fcba(image, size);
|
||||
if (!fcba)
|
||||
const fdbar_t *fdb = find_fd(image, size);
|
||||
if (!fcba) /* a valid fcba indicates a valid fdb */
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
chipset = guess_ich_chipset(fdb);
|
||||
/* TODO: port ifd_version and max_regions
|
||||
* against guess_ich_chipset()
|
||||
*/
|
||||
read_freq = (fcba->flcomp >> 17) & 7;
|
||||
|
||||
switch (read_freq) {
|
||||
|
@ -463,6 +531,19 @@ static void dump_fpsba(const fpsba_t *fpsba)
|
|||
for (i = 0; i < ARRAY_SIZE(fpsba->pchstrp); i++)
|
||||
printf("PCHSTRP%u:%s 0x%08x\n", i,
|
||||
i < 10 ? " " : "", fpsba->pchstrp[i]);
|
||||
|
||||
if (ifd_version >= IFD_VERSION_2) {
|
||||
printf("HAP bit is %sset\n",
|
||||
fpsba->pchstrp[0] & (1 << 16) ? "" : "not ");
|
||||
} else if (chipset >= CHIPSET_ICH8
|
||||
&& chipset <= CHIPSET_ICH10) {
|
||||
printf("ICH_MeDisable bit is %sset\n",
|
||||
fpsba->pchstrp[0] & 1 ? "" : "not ");
|
||||
} else {
|
||||
printf("AltMeDisable bit is %sset\n",
|
||||
fpsba->pchstrp[10] & (1 << 7) ? "" : "not ");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
@ -535,6 +616,13 @@ static void dump_fmsba(const fmsba_t *fmsba)
|
|||
printf("Found Processor Strap Section\n");
|
||||
for (i = 0; i < ARRAY_SIZE(fmsba->data); i++)
|
||||
printf("????: 0x%08x\n", fmsba->data[i]);
|
||||
|
||||
if (chipset >= CHIPSET_ICH8 && chipset <= CHIPSET_ICH10) {
|
||||
printf("MCH_MeDisable bit is %sset\n",
|
||||
fmsba->data[0] & 1 ? "" : "not ");
|
||||
printf("MCH_AltMeDisable bit is %sset\n",
|
||||
fmsba->data[0] & (1 << 7) ? "" : "not ");
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_jid(uint32_t jid)
|
||||
|
@ -633,6 +721,7 @@ static void dump_fd(char *image, int size)
|
|||
if (!fdb)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
printf("ICH Revision: %s\n", ich_chipset_names[chipset]);
|
||||
printf("FLMAP0: 0x%08x\n", fdb->flmap0);
|
||||
printf(" NR: %d\n", (fdb->flmap0 >> 24) & 7);
|
||||
printf(" FRBA: 0x%x\n", ((fdb->flmap0 >> 16) & 0xff) << 4);
|
||||
|
@ -933,6 +1022,47 @@ static void unlock_descriptor(const char *filename, char *image, int size)
|
|||
write_image(filename, image, size);
|
||||
}
|
||||
|
||||
/* Set the AltMeDisable (or HAP for >= IFD_VERSION_2) */
|
||||
void fpsba_set_altmedisable(fpsba_t *fpsba, fmsba_t *fmsba, bool altmedisable)
|
||||
{
|
||||
if (ifd_version >= IFD_VERSION_2) {
|
||||
printf("%sting the HAP bit to %s Intel ME...\n",
|
||||
altmedisable?"Set":"Unset",
|
||||
altmedisable?"disable":"enable");
|
||||
if (altmedisable)
|
||||
fpsba->pchstrp[0] |= (1 << 16);
|
||||
else
|
||||
fpsba->pchstrp[0] &= ~(1 << 16);
|
||||
} else {
|
||||
if (chipset >= CHIPSET_ICH8 && chipset <= CHIPSET_ICH10) {
|
||||
printf("%sting the ICH_MeDisable, MCH_MeDisable, "
|
||||
"and MCH_AltMeDisable to %s Intel ME...\n",
|
||||
altmedisable?"Set":"Unset",
|
||||
altmedisable?"disable":"enable");
|
||||
if (altmedisable) {
|
||||
/* MCH_MeDisable */
|
||||
fmsba->data[0] |= 1;
|
||||
/* MCH_AltMeDisable */
|
||||
fmsba->data[0] |= (1 << 7);
|
||||
/* ICH_MeDisable */
|
||||
fpsba->pchstrp[0] |= 1;
|
||||
} else {
|
||||
fmsba->data[0] &= ~1;
|
||||
fmsba->data[0] &= ~(1 << 7);
|
||||
fpsba->pchstrp[0] &= ~1;
|
||||
}
|
||||
} else {
|
||||
printf("%sting the AltMeDisable to %s Intel ME...\n",
|
||||
altmedisable?"Set":"Unset",
|
||||
altmedisable?"disable":"enable");
|
||||
if (altmedisable)
|
||||
fpsba->pchstrp[10] |= (1 << 7);
|
||||
else
|
||||
fpsba->pchstrp[10] &= ~(1 << 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void inject_region(const char *filename, char *image, int size,
|
||||
unsigned int region_type, const char *region_fname)
|
||||
{
|
||||
|
@ -1200,6 +1330,8 @@ static void print_usage(const char *name)
|
|||
" Dual Output Fast Read Support\n"
|
||||
" -l | --lock Lock firmware descriptor and ME region\n"
|
||||
" -u | --unlock Unlock firmware descriptor and ME region\n"
|
||||
" -M | --altmedisable <0|1> Set the AltMeDisable (or HAP for skylake or newer platform)\n"
|
||||
" bit to disable ME\n"
|
||||
" -p | --platform Add platform-specific quirks\n"
|
||||
" aplk - Apollo Lake\n"
|
||||
" cnl - Cannon Lake\n"
|
||||
|
@ -1217,6 +1349,7 @@ int main(int argc, char *argv[])
|
|||
int mode_dump = 0, mode_extract = 0, mode_inject = 0, mode_spifreq = 0;
|
||||
int mode_em100 = 0, mode_locked = 0, mode_unlocked = 0;
|
||||
int mode_layout = 0, mode_newlayout = 0, mode_density = 0;
|
||||
int mode_altmedisable = 0, altmedisable = 0;
|
||||
char *region_type_string = NULL, *region_fname = NULL;
|
||||
const char *layout_fname = NULL;
|
||||
int region_type = -1, inputfreq = 0;
|
||||
|
@ -1232,6 +1365,7 @@ int main(int argc, char *argv[])
|
|||
{"spifreq", 1, NULL, 's'},
|
||||
{"density", 1, NULL, 'D'},
|
||||
{"chip", 1, NULL, 'C'},
|
||||
{"altmedisable", 1, NULL, 'M'},
|
||||
{"em100", 0, NULL, 'e'},
|
||||
{"lock", 0, NULL, 'l'},
|
||||
{"unlock", 0, NULL, 'u'},
|
||||
|
@ -1241,7 +1375,7 @@ int main(int argc, char *argv[])
|
|||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "df:D:C:xi:n:s:p:eluvh?",
|
||||
while ((opt = getopt_long(argc, argv, "df:D:C:M:xi:n:s:p:eluvh?",
|
||||
long_options, &option_index)) != EOF) {
|
||||
switch (opt) {
|
||||
case 'd':
|
||||
|
@ -1345,6 +1479,15 @@ int main(int argc, char *argv[])
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
case 'M':
|
||||
mode_altmedisable = 1;
|
||||
altmedisable = strtol(optarg, NULL, 0);
|
||||
if (altmedisable > 1) {
|
||||
fprintf(stderr, "error: Illegal value\n");
|
||||
print_usage(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
// Parse the requested SPI frequency
|
||||
inputfreq = strtol(optarg, NULL, 0);
|
||||
|
@ -1422,7 +1565,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
if ((mode_dump + mode_layout + mode_extract + mode_inject +
|
||||
mode_newlayout + (mode_spifreq | mode_em100 | mode_unlocked |
|
||||
mode_locked)) > 1) {
|
||||
mode_locked) + mode_altmedisable) > 1) {
|
||||
fprintf(stderr, "You may not specify more than one mode.\n\n");
|
||||
print_usage(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
|
@ -1430,7 +1573,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
if ((mode_dump + mode_layout + mode_extract + mode_inject +
|
||||
mode_newlayout + mode_spifreq + mode_em100 + mode_locked +
|
||||
mode_unlocked + mode_density) == 0) {
|
||||
mode_unlocked + mode_density + mode_altmedisable) == 0) {
|
||||
fprintf(stderr, "You need to specify a mode.\n\n");
|
||||
print_usage(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
|
@ -1503,6 +1646,13 @@ int main(int argc, char *argv[])
|
|||
if (mode_unlocked)
|
||||
unlock_descriptor(filename, image, size);
|
||||
|
||||
if (mode_altmedisable) {
|
||||
fpsba_t *fpsba = find_fpsba(image, size);
|
||||
fmsba_t *fmsba = find_fmsba(image, size);
|
||||
fpsba_set_altmedisable(fpsba, fmsba, altmedisable);
|
||||
write_image(filename, image, size);
|
||||
}
|
||||
|
||||
free(image);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#define IFDTOOL_VERSION "1.2"
|
||||
|
||||
enum ifd_version {
|
||||
|
@ -21,6 +22,36 @@ enum ifd_version {
|
|||
IFD_VERSION_2,
|
||||
};
|
||||
|
||||
/* port from flashrom */
|
||||
enum ich_chipset {
|
||||
CHIPSET_ICH_UNKNOWN,
|
||||
CHIPSET_ICH,
|
||||
CHIPSET_ICH2345,
|
||||
CHIPSET_ICH6,
|
||||
CHIPSET_POULSBO, /* SCH U* */
|
||||
CHIPSET_TUNNEL_CREEK, /* Atom E6xx */
|
||||
CHIPSET_CENTERTON, /* Atom S1220 S1240 S1260 */
|
||||
CHIPSET_ICH7,
|
||||
CHIPSET_ICH8,
|
||||
CHIPSET_ICH9,
|
||||
CHIPSET_ICH10,
|
||||
CHIPSET_5_SERIES_IBEX_PEAK,
|
||||
CHIPSET_6_SERIES_COUGAR_POINT,
|
||||
CHIPSET_7_SERIES_PANTHER_POINT,
|
||||
CHIPSET_8_SERIES_LYNX_POINT,
|
||||
CHIPSET_BAYTRAIL, /* Actually all with Silvermont architecture:
|
||||
* Bay Trail, Avoton/Rangeley
|
||||
*/
|
||||
CHIPSET_8_SERIES_LYNX_POINT_LP,
|
||||
CHIPSET_8_SERIES_WELLSBURG,
|
||||
CHIPSET_9_SERIES_WILDCAT_POINT,
|
||||
CHIPSET_9_SERIES_WILDCAT_POINT_LP,
|
||||
CHIPSET_100_SERIES_SUNRISE_POINT, /* also 6th/7th gen Core i/o (LP)
|
||||
* variants
|
||||
*/
|
||||
CHIPSET_C620_SERIES_LEWISBURG,
|
||||
};
|
||||
|
||||
enum platform {
|
||||
PLATFORM_APL,
|
||||
PLATFORM_CNL,
|
||||
|
|
Loading…
Reference in New Issue