mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-26 22:52:34 +02:00
ichspi: Expose flash descriptor regions through get_region()
Region attributes are now stored in a `fd_regions` array after being decoded in ich9_handle_frap() and used by ich_get_region(). A special cases is handled in ich_get_region(): if there is a gap between two flash regions, an artificial region is created to fill the gap. I.e. any address inside the gap will return a region that spans the gap between the end the of the previous region and the start of the next region. This allows ich_get_region() to be used to iterate the entire flash region-by-region. Read and write operations are assumed to be allowed inside gaps between regions. BUG=b:260440773 BRANCH=none TEST=flashrom -{r,w,E,v} on dedede (JSL) Change-Id: I019f3f407f6a2a82f686a168457e0e32961ff483 Signed-off-by: Nikolai Artemiev <nartemiev@google.com> Reviewed-on: https://review.coreboot.org/c/flashrom/+/70127 Reviewed-by: Edward O'Callaghan <quasisec@chromium.org> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
0741727925
commit
6cb1bd6fe3
76
ichspi.c
76
ichspi.c
@ -1262,12 +1262,22 @@ static int ich_spi_send_command(const struct flashctx *flash, unsigned int write
|
||||
return result;
|
||||
}
|
||||
|
||||
#define MAX_FD_REGIONS 16
|
||||
struct fd_region {
|
||||
const char* name;
|
||||
enum ich_access_protection level;
|
||||
uint32_t base;
|
||||
uint32_t limit;
|
||||
};
|
||||
|
||||
struct hwseq_data {
|
||||
uint32_t size_comp0;
|
||||
uint32_t size_comp1;
|
||||
uint32_t addr_mask;
|
||||
bool only_4k;
|
||||
uint32_t hsfc_fcycle;
|
||||
|
||||
struct fd_region fd_regions[MAX_FD_REGIONS];
|
||||
};
|
||||
|
||||
static struct hwseq_data *get_hwseq_data_from_context(const struct flashctx *flash)
|
||||
@ -1401,6 +1411,57 @@ static int ich_exec_sync_hwseq_xfer(const struct flashctx *flash, uint32_t hsfc_
|
||||
return ich_hwseq_wait_for_cycle_complete(len, ich_gen, addr_mask);
|
||||
}
|
||||
|
||||
static void ich_get_region(const struct flashctx *flash, unsigned int addr, struct flash_region *region)
|
||||
{
|
||||
struct ich_descriptors desc = { 0 };
|
||||
const ssize_t nr = ich_number_of_regions(ich_generation, &desc.content);
|
||||
const struct hwseq_data *hwseq_data = get_hwseq_data_from_context(flash);
|
||||
const struct fd_region *fd_regions = hwseq_data->fd_regions;
|
||||
|
||||
/*
|
||||
* Set default values for the region. If no flash descriptor containing
|
||||
* addr is found, these values will be used instead.
|
||||
*
|
||||
* The region start and end are constrained so that they do not overlap
|
||||
* any flash descriptor regions.
|
||||
*/
|
||||
const char *name = "";
|
||||
region->read_prot = false;
|
||||
region->write_prot = false;
|
||||
region->start = 0;
|
||||
region->end = flashrom_flash_getsize(flash);
|
||||
|
||||
for (ssize_t i = 0; i < nr; i++) {
|
||||
uint32_t base = fd_regions[i].base;
|
||||
uint32_t limit = fd_regions[i].limit;
|
||||
enum ich_access_protection level = fd_regions[i].level;
|
||||
|
||||
if (addr < base) {
|
||||
/*
|
||||
* fd_regions[i] starts after addr, constrain
|
||||
* region->end so that it does not overlap.
|
||||
*/
|
||||
region->end = min(region->end, base);
|
||||
} else if (addr > limit) {
|
||||
/*
|
||||
* fd_regions[i] ends before addr, constrain
|
||||
* region->start so that it does not overlap.
|
||||
*/
|
||||
region->start = max(region->start, limit + 1);
|
||||
} else {
|
||||
/* fd_regions[i] contains addr, copy to *region. */
|
||||
name = fd_regions[i].name;
|
||||
region->start = base;
|
||||
region->end = limit + 1;
|
||||
region->read_prot = (level == LOCKED) || (level == READ_PROT);
|
||||
region->write_prot = (level == LOCKED) || (level == WRITE_PROT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
region->name = strdup(name);
|
||||
}
|
||||
|
||||
/* Given RDID info, return pointer to entry in flashchips[] */
|
||||
static const struct flashchip *flash_id_to_entry(uint32_t mfg_id, uint32_t model_id)
|
||||
{
|
||||
@ -1768,7 +1829,8 @@ static const char *const access_names[] = {
|
||||
"read-write", "write-only", "read-only", "locked"
|
||||
};
|
||||
|
||||
static enum ich_access_protection ich9_handle_frap(uint32_t frap, unsigned int i)
|
||||
static enum ich_access_protection ich9_handle_frap(struct fd_region *fd_regions,
|
||||
uint32_t frap, unsigned int i)
|
||||
{
|
||||
static const char *const region_names[] = {
|
||||
"Flash Descriptor", "BIOS", "Management Engine",
|
||||
@ -1811,6 +1873,12 @@ static enum ich_access_protection ich9_handle_frap(uint32_t frap, unsigned int i
|
||||
msg_pinfo("FREG%u: %s region (0x%08x-0x%08x) is %s.\n", i,
|
||||
region_name, base, limit, access_names[rwperms]);
|
||||
|
||||
/* Save region attributes for use by ich_get_region(). */
|
||||
fd_regions[i].base = base;
|
||||
fd_regions[i].limit = limit;
|
||||
fd_regions[i].level = rwperms;
|
||||
fd_regions[i].name = region_name;
|
||||
|
||||
return rwperms;
|
||||
}
|
||||
|
||||
@ -1904,6 +1972,7 @@ static const struct opaque_master opaque_master_ich_hwseq = {
|
||||
.erase = ich_hwseq_block_erase,
|
||||
.read_register = ich_hwseq_read_status,
|
||||
.write_register = ich_hwseq_write_status,
|
||||
.get_region = ich_get_region,
|
||||
.shutdown = ich_hwseq_shutdown,
|
||||
};
|
||||
|
||||
@ -2047,8 +2116,7 @@ static int init_ich_default(const struct programmer_cfg *cfg, void *spibar, enum
|
||||
struct ich_descriptors desc = { 0 };
|
||||
enum ich_spi_mode ich_spi_mode = ich_auto;
|
||||
size_t num_freg, num_pr, reg_pr0;
|
||||
|
||||
struct hwseq_data hwseq_data;
|
||||
struct hwseq_data hwseq_data = { 0 };
|
||||
init_chipset_properties(&swseq_data, &hwseq_data, &num_freg, &num_pr, ®_pr0, ich_gen);
|
||||
|
||||
int ret = get_ich_spi_mode_param(cfg, &ich_spi_mode);
|
||||
@ -2109,7 +2177,7 @@ static int init_ich_default(const struct programmer_cfg *cfg, void *spibar, enum
|
||||
|
||||
/* Handle FREGx and FRAP registers */
|
||||
for (i = 0; i < num_freg; i++)
|
||||
ich_spi_rw_restricted |= ich9_handle_frap(tmp, i);
|
||||
ich_spi_rw_restricted |= ich9_handle_frap(hwseq_data.fd_regions, tmp, i);
|
||||
if (ich_spi_rw_restricted)
|
||||
msg_pinfo("Not all flash regions are freely accessible by flashrom. This is "
|
||||
"most likely\ndue to an active ME. Please see "
|
||||
|
Loading…
x
Reference in New Issue
Block a user