From 22c621aed228b63f36f756c0016b2a7dac0e8d0b Mon Sep 17 00:00:00 2001 From: Aarya Chaumal Date: Fri, 15 Jul 2022 16:51:27 +0530 Subject: [PATCH] flashrom.c:Add function to get a flattened view of the chip erase blocks Add a function to flatten out the addresses of the flash chip as per the different erase functions. This function will return a list of layouts which is dynamically allocated. So after use all the layouts as well as the list itself should be freed. The free_erase_layout function does that. Change-Id: Iafe78de00daa55f7114bd4ce09465dd88074ece4 Signed-off-by: Aarya Chaumal --- flashrom.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++ include/flash.h | 15 ++++++++++ 2 files changed, 95 insertions(+) diff --git a/flashrom.c b/flashrom.c index cb4eb324e..d3f802bf6 100644 --- a/flashrom.c +++ b/flashrom.c @@ -1062,6 +1062,86 @@ static int walk_by_layout(struct flashctx *const flashctx, struct walk_info *con return 0; } +static void free_erase_layout(struct erase_layout *layout, int erasefn_count); + +static void free_erase_layout(struct erase_layout *layout, int erasefn_count) +{ + if (layout) { + for (int i = 0; i < erasefn_count; i++) { + free(layout[i].layout_list); + } + free(layout); + } +} + +struct erase_layout *create_erase_layout(struct flashctx *const flashctx); + +struct erase_layout *create_erase_layout(struct flashctx *const flashctx) +{ + struct flashchip *chip = flashctx->chip; + struct erase_layout *layout; + size_t erasefn_count = count_usable_erasers(flashctx); + layout = (struct erase_layout *)malloc(sizeof(struct erase_layout) * erasefn_count); + + if (layout == NULL) + return NULL; + + size_t i; + size_t index = 0; + for (i = 0; i < NUM_ERASEFUNCTIONS; i++) { + if (check_block_eraser(flashctx, i, 0)) + continue; + layout[index].erasefn = chip->block_erasers[i].block_erase; + size_t block_count = 0; + size_t sub_block_index = 0; + chipoff_t addr = 0; + + int j = 0; + while(addr < chip->total_size * 1024) { + block_count += chip->block_erasers[i].eraseblocks[j].count; + addr += chip->block_erasers[i].eraseblocks[j].size * chip->block_erasers[i].eraseblocks[j].count; + j++; + } + layout[index].block_count = block_count; + layout[index].layout_list = (struct eraseblock_data *)malloc(sizeof(struct eraseblock_data) * block_count); + + if (layout[index].layout_list == NULL) + { + free_erase_layout(layout, index); + return NULL; + } + + size_t block_num = 0; + chipoff_t start_addr = 0; + chipoff_t end_addr = 0; + + for (j = 0; block_num < block_count; j++) { + size_t num; + + for (num = 0; num < chip->block_erasers[i].eraseblocks[j].count; num++) { + end_addr = start_addr + chip->block_erasers[i].eraseblocks[j].size - 1; + layout[index].layout_list[block_num].start_addr = start_addr; + layout[index].layout_list[block_num].end_addr = end_addr; + layout[index].layout_list[block_num].selected = false; + layout[index].layout_list[block_num].block_num = block_num; + if (index > 0) { + layout[index].layout_list[block_num].first_sub_block_index = sub_block_index; + while (layout[index-1].layout_list[sub_block_index].start_addr >= start_addr && + layout[index-1].layout_list[sub_block_index].end_addr <= end_addr && + sub_block_index < layout[index-1].block_count) { + sub_block_index++; + } + layout[index].layout_list[block_num].last_sub_block_index = sub_block_index - 1; + } + block_num += 1; + start_addr = end_addr + 1; + } + } + index++; + } + return layout; +} + static int erase_block(struct flashctx *const flashctx, const struct walk_info *const info, const erasefn_t erasefn) { diff --git a/include/flash.h b/include/flash.h index 79aaa64a8..7841e12bb 100644 --- a/include/flash.h +++ b/include/flash.h @@ -359,6 +359,21 @@ struct flashrom_flashctx { struct flashrom_progress *progress_state; }; +struct eraseblock_data { + chipoff_t start_addr; + chipoff_t end_addr; + bool selected; + size_t block_num; + size_t first_sub_block_index; + size_t last_sub_block_index; +}; + +struct erase_layout { + struct eraseblock_data* layout_list; + size_t block_count; + erasefunc_t* erasefn; +}; + /* Timing used in probe routines. ZERO is -2 to differentiate between an unset * field and zero delay. *