|
@ -125,15 +125,36 @@ static fmsba_t *find_fmsba(char *image, int size) |
|
|
return PTR_IN_RANGE(fmsba, image, size) ? fmsba : NULL; |
|
|
return PTR_IN_RANGE(fmsba, image, size) ? fmsba : NULL; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
* 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 |
|
|
|
|
|
* have the required FCBA field, but are IFD v2 and return true if current |
|
|
|
|
|
* platform is one of them. |
|
|
|
|
|
*/ |
|
|
|
|
|
static int is_platform_ifd_2(void) |
|
|
|
|
|
{ |
|
|
|
|
|
static const int ifd_2_platforms[] = { |
|
|
|
|
|
PLATFORM_GLK, |
|
|
|
|
|
PLATFORM_CNL, |
|
|
|
|
|
}; |
|
|
|
|
|
unsigned int i; |
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(ifd_2_platforms); i++) { |
|
|
|
|
|
if (platform == ifd_2_platforms[i]) |
|
|
|
|
|
return 1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/* |
|
|
/* |
|
|
* There is no version field in the descriptor so to determine |
|
|
* There is no version field in the descriptor so to determine |
|
|
* if this is a new descriptor format we check the hardcoded SPI |
|
|
* if this is a new descriptor format we check the hardcoded SPI |
|
|
* read frequency to see if it is fixed at 20MHz or 17MHz. |
|
|
* read frequency to see if it is fixed at 20MHz or 17MHz. |
|
|
*/ |
|
|
*/ |
|
|
static void check_ifd_version(char *image, int size) |
|
|
|
|
|
|
|
|
static int get_ifd_version_from_fcba(char *image, int size) |
|
|
{ |
|
|
{ |
|
|
int read_freq; |
|
|
int read_freq; |
|
|
|
|
|
|
|
|
const fcba_t *fcba = find_fcba(image, size); |
|
|
const fcba_t *fcba = find_fcba(image, size); |
|
|
if (!fcba) |
|
|
if (!fcba) |
|
|
exit(EXIT_FAILURE); |
|
|
exit(EXIT_FAILURE); |
|
@ -142,14 +163,10 @@ static void check_ifd_version(char *image, int size) |
|
|
|
|
|
|
|
|
switch (read_freq) { |
|
|
switch (read_freq) { |
|
|
case SPI_FREQUENCY_20MHZ: |
|
|
case SPI_FREQUENCY_20MHZ: |
|
|
ifd_version = IFD_VERSION_1; |
|
|
|
|
|
max_regions = MAX_REGIONS_OLD; |
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
return IFD_VERSION_1; |
|
|
case SPI_FREQUENCY_17MHZ: |
|
|
case SPI_FREQUENCY_17MHZ: |
|
|
case SPI_FREQUENCY_50MHZ_30MHZ: |
|
|
case SPI_FREQUENCY_50MHZ_30MHZ: |
|
|
ifd_version = IFD_VERSION_2; |
|
|
|
|
|
max_regions = MAX_REGIONS; |
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
return IFD_VERSION_2; |
|
|
default: |
|
|
default: |
|
|
fprintf(stderr, "Unknown descriptor version: %d\n", |
|
|
fprintf(stderr, "Unknown descriptor version: %d\n", |
|
|
read_freq); |
|
|
read_freq); |
|
@ -157,6 +174,19 @@ static void check_ifd_version(char *image, int size) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void check_ifd_version(char *image, int size) |
|
|
|
|
|
{ |
|
|
|
|
|
if (is_platform_ifd_2()) |
|
|
|
|
|
ifd_version = IFD_VERSION_2; |
|
|
|
|
|
else |
|
|
|
|
|
ifd_version = get_ifd_version_from_fcba(image, size); |
|
|
|
|
|
|
|
|
|
|
|
if (ifd_version == IFD_VERSION_1) |
|
|
|
|
|
max_regions = MAX_REGIONS_OLD; |
|
|
|
|
|
else |
|
|
|
|
|
max_regions = MAX_REGIONS; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
static region_t get_region(const frba_t *frba, unsigned int region_type) |
|
|
static region_t get_region(const frba_t *frba, unsigned int region_type) |
|
|
{ |
|
|
{ |
|
|
int base_mask; |
|
|
int base_mask; |
|
@ -816,7 +846,8 @@ static void lock_descriptor(const char *filename, char *image, int size) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
switch (platform) { |
|
|
switch (platform) { |
|
|
case PLATFORM_APOLLOLAKE: |
|
|
|
|
|
|
|
|
case PLATFORM_APL: |
|
|
|
|
|
case PLATFORM_GLK: |
|
|
/* CPU/BIOS can read descriptor and BIOS */ |
|
|
/* CPU/BIOS can read descriptor and BIOS */ |
|
|
fmba->flmstr1 |= 0x3 << rd_shift; |
|
|
fmba->flmstr1 |= 0x3 << rd_shift; |
|
|
/* CPU/BIOS can write BIOS */ |
|
|
/* CPU/BIOS can write BIOS */ |
|
@ -826,6 +857,24 @@ static void lock_descriptor(const char *filename, char *image, int size) |
|
|
/* TXE can only write Device Expansion */ |
|
|
/* TXE can only write Device Expansion */ |
|
|
fmba->flmstr2 |= 0x20 << wr_shift; |
|
|
fmba->flmstr2 |= 0x20 << wr_shift; |
|
|
break; |
|
|
break; |
|
|
|
|
|
case PLATFORM_SKLKBL: |
|
|
|
|
|
/* CPU/BIOS can read descriptor, BIOS and GbE. */ |
|
|
|
|
|
fmba->flmstr1 |= 0xb << rd_shift; |
|
|
|
|
|
/* CPU/BIOS can write BIOS and Gbe. */ |
|
|
|
|
|
fmba->flmstr1 |= 0xa << wr_shift; |
|
|
|
|
|
/* ME can read descriptor, ME and GbE. */ |
|
|
|
|
|
fmba->flmstr2 |= 0xd << rd_shift; |
|
|
|
|
|
/* ME can write ME. */ |
|
|
|
|
|
fmba->flmstr2 |= 0x4 << wr_shift; |
|
|
|
|
|
/* GbE can read GbE and descriptor. */ |
|
|
|
|
|
fmba->flmstr3 |= 0x9 << rd_shift; |
|
|
|
|
|
/* GbE can write GbE. */ |
|
|
|
|
|
fmba->flmstr3 |= 0x8 << wr_shift; |
|
|
|
|
|
/* EC can read EC and descriptor. */ |
|
|
|
|
|
fmba->flmstr5 |= 0x101 << rd_shift; |
|
|
|
|
|
/* EC can write EC region. */ |
|
|
|
|
|
fmba->flmstr5 |= 0x100 << wr_shift; |
|
|
|
|
|
break; |
|
|
default: |
|
|
default: |
|
|
/* CPU/BIOS can read descriptor, BIOS, and GbE. */ |
|
|
/* CPU/BIOS can read descriptor, BIOS, and GbE. */ |
|
|
fmba->flmstr1 |= 0xb << rd_shift; |
|
|
fmba->flmstr1 |= 0xb << rd_shift; |
|
@ -1135,6 +1184,9 @@ static void print_usage(const char *name) |
|
|
" -u | --unlock Unlock firmware descriptor and ME region\n" |
|
|
" -u | --unlock Unlock firmware descriptor and ME region\n" |
|
|
" -p | --platform Add platform-specific quirks\n" |
|
|
" -p | --platform Add platform-specific quirks\n" |
|
|
" aplk - Apollo Lake\n" |
|
|
" aplk - Apollo Lake\n" |
|
|
|
|
|
" cnl - Cannon Lake\n" |
|
|
|
|
|
" glk - Gemini Lake\n" |
|
|
|
|
|
" sklkbl - Skylake/Kaby Lake\n" |
|
|
" -v | --version: print the version\n" |
|
|
" -v | --version: print the version\n" |
|
|
" -h | --help: print this help\n\n" |
|
|
" -h | --help: print this help\n\n" |
|
|
"<region> is one of Descriptor, BIOS, ME, GbE, Platform\n" |
|
|
"<region> is one of Descriptor, BIOS, ME, GbE, Platform\n" |
|
@ -1324,11 +1376,18 @@ int main(int argc, char *argv[]) |
|
|
break; |
|
|
break; |
|
|
case 'p': |
|
|
case 'p': |
|
|
if (!strcmp(optarg, "aplk")) { |
|
|
if (!strcmp(optarg, "aplk")) { |
|
|
platform = PLATFORM_APOLLOLAKE; |
|
|
|
|
|
|
|
|
platform = PLATFORM_APL; |
|
|
|
|
|
} else if (!strcmp(optarg, "cnl")) { |
|
|
|
|
|
platform = PLATFORM_CNL; |
|
|
|
|
|
} else if (!strcmp(optarg, "glk")) { |
|
|
|
|
|
platform = PLATFORM_GLK; |
|
|
|
|
|
} else if (!strcmp(optarg, "sklkbl")) { |
|
|
|
|
|
platform = PLATFORM_SKLKBL; |
|
|
} else { |
|
|
} else { |
|
|
fprintf(stderr, "Unknown platform: %s\n", optarg); |
|
|
fprintf(stderr, "Unknown platform: %s\n", optarg); |
|
|
exit(EXIT_FAILURE); |
|
|
exit(EXIT_FAILURE); |
|
|
} |
|
|
} |
|
|
|
|
|
fprintf(stderr, "Platform is: %s\n", optarg); |
|
|
break; |
|
|
break; |
|
|
case 'v': |
|
|
case 'v': |
|
|
print_version(); |
|
|
print_version(); |
|
|