Skip to content

Commit

Permalink
Check PR ranges when deciding if range is wp protected
Browse files Browse the repository at this point in the history
Change-Id: I989006eae97f5e015df20026b6f5361ad41223c1
Signed-off-by: Michał Iwanicki <[email protected]>
  • Loading branch information
m-iwanicki committed Dec 6, 2024
1 parent 4dc3fa9 commit e7b4efa
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 39 deletions.
25 changes: 20 additions & 5 deletions flashrom.c
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,16 @@ void get_flash_region(const struct flashctx *flash, int addr, struct flash_regio
}
}

struct protected_ranges get_protected_ranges(const struct flashctx *flash) {
struct protected_ranges ranges = { 0 };
if ((flash->mst->buses_supported & BUS_PROG) && flash->mst->opaque.get_region
&& flash->mst->opaque.get_protected_ranges)
{
ranges = flash->mst->opaque.get_protected_ranges();
}
return ranges;
}

int check_for_unwritable_regions(const struct flashctx *flash, unsigned int start, unsigned int len)
{
struct flash_region region;
Expand Down Expand Up @@ -1745,6 +1755,7 @@ static int write_protect_check(struct flashctx *flash) {
struct flashrom_wp_cfg *cfg = NULL;
const struct romentry *entry = NULL;
const struct flashrom_layout *const layout = get_layout(flash);
struct protected_ranges ranges = get_protected_ranges(flash);

if (flashrom_wp_cfg_new(&cfg) == FLASHROM_WP_OK &&
flashrom_wp_read_cfg(cfg, flash) == FLASHROM_WP_OK )
Expand All @@ -1757,14 +1768,18 @@ static int write_protect_check(struct flashctx *flash) {
flashrom_wp_cfg_release(cfg);

while ((entry = layout_next_included(layout, entry))) {
if ((!flash->flags.skip_unwritable_regions &&
check_for_unwritable_regions(flash, entry->region.start, entry->region.end - entry->region.start)
)
||
(check_wp && entry->region.start < wp_start + wp_len && wp_start <= entry->region.end))
if (!flash->flags.skip_unwritable_regions &&
check_for_unwritable_regions(flash, entry->region.start, entry->region.end - entry->region.start))
{
return -1;
}
if (check_wp && entry->region.start < wp_start + wp_len && wp_start <= entry->region.end)
return -1;
for (int i = 0; i < ranges.count; ++i) {
struct protected_range prot = ranges.ranges[i];
if (prot.write_prot && entry->region.start < prot.base + prot.limit && prot.base <= entry->region.end)
return -1;
}
}

return 0;
Expand Down
56 changes: 22 additions & 34 deletions ichspi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1290,18 +1290,12 @@ struct hwseq_data {
};

#define MAX_PR_REGISTERS 6
struct pr_register {
enum ich_access_protection level;
uint32_t base;
uint32_t limit;
struct protected_range _ranges[MAX_PR_REGISTERS];
struct protected_ranges ranges = {
.count = 0,
.ranges = _ranges,
};

struct _pr_access {
uint8_t count;
struct pr_register registers[MAX_PR_REGISTERS];
};
struct _pr_access pr_access;

static struct hwseq_data *get_hwseq_data_from_context(const struct flashctx *flash)
{
return flash->mst->opaque.data;
Expand Down Expand Up @@ -1477,24 +1471,17 @@ static void ich_get_region(const struct flashctx *flash, unsigned int addr, stru
region->end = limit;
region->read_prot = (level == LOCKED) || (level == READ_PROT);
region->write_prot = (level == LOCKED) || (level == WRITE_PROT);
if (region->write_prot != true) {
for (ssize_t pr = 0; pr < pr_access.count; pr++) {
struct pr_register pr_reg = pr_access.registers[pr];
if (pr_reg.level == WRITE_PROT &&
region->start < pr_reg.base + pr_reg.limit && pr_reg.base <= region->end)
{
region->write_prot = true;
break;
}
}
}
break;
}
}

region->name = strdup(name);
}

static struct protected_ranges ich_get_protected_ranges() {
return ranges;
}

/* 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)
{
Expand Down Expand Up @@ -1974,32 +1961,33 @@ static enum ich_access_protection ich9_handle_region_access(struct fd_region *fd
#define ICH_PR_PERMS(pr) (((~((pr) >> PR_RP_OFF) & 1) << 0) | \
((~((pr) >> PR_WP_OFF) & 1) << 1))

static struct pr_register ich9_handle_pr(const size_t reg_pr0, unsigned int i)
static enum ich_access_protection ich9_handle_pr(const size_t reg_pr0, unsigned int i, struct protected_range* prot)
{
uint8_t off = reg_pr0 + (i * 4);
uint32_t pr = mmio_readl(ich_spibar + off);
unsigned int rwperms_idx = ICH_PR_PERMS(pr);
struct pr_register pr_reg = {
.level = access_perms_to_protection[rwperms_idx],
.base = ICH_FREG_BASE(pr),
.limit = ICH_FREG_LIMIT(pr),
};
enum ich_access_protection rwperms = access_perms_to_protection[rwperms_idx];

prot->base = ICH_FREG_BASE(pr);
prot->limit = ICH_FREG_LIMIT(pr);
prot->write_prot = rwperms == WRITE_PROT;
prot->read_prot = rwperms == READ_PROT || rwperms == LOCKED;

/* From 5 on we have GPR registers and start from 0 again. */
const char *const prefix = i >= 5 ? "G" : "";
if (i >= 5)
i -= 5;

if (pr_reg.level == NO_PROT) {
if (rwperms == NO_PROT) {
msg_pdbg2("0x%02"PRIX8": 0x%08"PRIx32" (%sPR%u is unused)\n", off, pr, prefix, i);
return pr_reg;
return NO_PROT;
}

msg_pdbg("0x%02"PRIX8": 0x%08"PRIx32" ", off, pr);
msg_pwarn("%sPR%u: Warning: 0x%08"PRIx32"-0x%08"PRIx32" is %s.\n", prefix, i, ICH_FREG_BASE(pr),
ICH_FREG_LIMIT(pr), access_names[pr_reg.level]);
ICH_FREG_LIMIT(pr), access_names[rwperms]);

return pr_reg;
return rwperms;
}

/* Set/Clear the read and write protection enable bits of PR register @i
Expand Down Expand Up @@ -2047,6 +2035,7 @@ static const struct opaque_master opaque_master_ich_hwseq = {
.read_register = ich_hwseq_read_status,
.write_register = ich_hwseq_write_status,
.get_region = ich_get_region,
.get_protected_ranges = ich_get_protected_ranges,
.shutdown = ich_hwseq_shutdown,
};

Expand Down Expand Up @@ -2198,7 +2187,6 @@ static int init_ich_default(const struct programmer_cfg *cfg, void *spibar, enum
size_t num_freg, num_pr, reg_pr0;
struct hwseq_data hwseq_data = { 0 };
init_chipset_properties(&swseq_data, &hwseq_data, &num_freg, &num_pr, &reg_pr0, ich_gen);
pr_access.count = num_pr;

int ret = get_ich_spi_mode_param(cfg, &ich_spi_mode);
if (ret)
Expand Down Expand Up @@ -2268,12 +2256,12 @@ static int init_ich_default(const struct programmer_cfg *cfg, void *spibar, enum
}

/* Handle PR registers */
ranges.count = num_pr;
for (i = 0; i < num_pr; i++) {
/* if not locked down try to disable PR locks first */
if (!ichspi_lock)
ich9_set_pr(reg_pr0, i, 0, 0);
pr_access.registers[i] = ich9_handle_pr(reg_pr0, i);
ich_spi_rw_restricted |= pr_access.registers[i].level;
ich_spi_rw_restricted |= ich9_handle_pr(reg_pr0, i, &_ranges[i]);
}

switch (ich_spi_rw_restricted) {
Expand Down
13 changes: 13 additions & 0 deletions include/layout.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,18 @@ struct romentry {
struct flash_region region;
};

struct protected_range {
uint32_t base;
uint32_t limit;
bool read_prot;
bool write_prot;
};

struct protected_ranges {
int count;
const struct protected_range *ranges;
};

struct flashrom_layout;

struct layout_include_args;
Expand All @@ -79,5 +91,6 @@ void prepare_layout_for_extraction(struct flashrom_flashctx *);
int layout_sanity_checks(const struct flashrom_flashctx *);
int check_for_unwritable_regions(const struct flashrom_flashctx *flash, unsigned int start, unsigned int len);
void get_flash_region(const struct flashrom_flashctx *flash, int addr, struct flash_region *region);
struct protected_ranges get_protected_ranges(const struct flashrom_flashctx *flash);

#endif /* !__LAYOUT_H__ */
1 change: 1 addition & 0 deletions include/programmer.h
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,7 @@ struct opaque_master {
enum flashrom_wp_result (*wp_read_cfg)(struct flashrom_wp_cfg *, struct flashctx *);
enum flashrom_wp_result (*wp_get_ranges)(struct flashrom_wp_ranges **, struct flashctx *);
void (*get_region)(const struct flashctx *flash, unsigned int addr, struct flash_region *region);
struct protected_ranges (*get_protected_ranges)();
int (*shutdown)(void *data);
void (*delay) (const struct flashctx *flash, unsigned int usecs);
void *data;
Expand Down

0 comments on commit e7b4efa

Please sign in to comment.