Representing each group write protection flag with only one bit instead of int variable significantly reduces memory consumption.
Signed-off-by: Igor Mitsyanko <i.mitsya...@samsung.com> --- hw/sd.c | 36 ++++++++++++++++++++++-------------- 1 files changed, 22 insertions(+), 14 deletions(-) diff --git a/hw/sd.c b/hw/sd.c index 07eb263..23e5f2f 100644 --- a/hw/sd.c +++ b/hw/sd.c @@ -81,7 +81,7 @@ struct SDState { uint8_t sd_status[64]; uint32_t vhs; int wp_switch; - int *wp_groups; + uint8_t *wp_groups; uint64_t size; int blk_len; uint32_t erase_start; @@ -415,7 +415,7 @@ static void sd_reset(SDState *sd, BlockDriverState *bdrv) if (sd->wp_groups) g_free(sd->wp_groups); sd->wp_switch = bdrv ? bdrv_is_read_only(bdrv) : 0; - sd->wp_groups = (int *) g_malloc0(sizeof(int) * sect); + sd->wp_groups = (uint8_t *)g_malloc0((sect >> 3) + 1); memset(sd->function_group, 0, sizeof(int) * 6); sd->erase_start = 0; sd->erase_end = 0; @@ -484,9 +484,11 @@ static void sd_erase(SDState *sd) sd->erase_end = 0; sd->csd[14] |= 0x40; - for (i = start; i <= end; i ++) - if (sd->wp_groups[i]) + for (i = start; i <= end; i++) { + if (sd->wp_groups[i >> 3] & (1 << (i & 0x7))) { sd->card_status |= WP_ERASE_SKIP; + } + } } static uint32_t sd_wpbits(SDState *sd, uint64_t addr) @@ -496,9 +498,12 @@ static uint32_t sd_wpbits(SDState *sd, uint64_t addr) wpnum = addr >> (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT); - for (i = 0; i < 32; i ++, wpnum ++, addr += WPGROUP_SIZE) - if (addr < sd->size && sd->wp_groups[wpnum]) + for (i = 0; i < 32; i++, wpnum++, addr += WPGROUP_SIZE) { + if (addr < sd->size && + (sd->wp_groups[wpnum >> 3] & (1 << (wpnum & 0x7)))) { ret |= (1 << i); + } + } return ret; } @@ -536,8 +541,9 @@ static void sd_function_switch(SDState *sd, uint32_t arg) static inline int sd_wp_addr(SDState *sd, uint32_t addr) { - return sd->wp_groups[addr >> - (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT)]; + unsigned int grp = addr >> + (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT); + return sd->wp_groups[grp >> 3] & (1 << (grp & 0x7)) ? 1 : 0; } static void sd_lock_command(SDState *sd) @@ -560,8 +566,8 @@ static void sd_lock_command(SDState *sd) sd->card_status |= LOCK_UNLOCK_FAILED; return; } - memset(sd->wp_groups, 0, sizeof(int) * (sd->size >> - (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT))); + memset(sd->wp_groups, 0, 1 + (sd->size >> + (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT + 3))); sd->csd[14] &= ~0x10; sd->card_status &= ~CARD_IS_LOCKED; sd->pwd_len = 0; @@ -1007,8 +1013,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, } sd->state = sd_programming_state; - sd->wp_groups[addr >> (HWBLOCK_SHIFT + - SECTOR_SHIFT + WPGROUP_SHIFT)] = 1; + sd->wp_groups[addr >> (HWBLOCK_SHIFT + SECTOR_SHIFT + + WPGROUP_SHIFT + 3)] |= 1 << ((addr >> (HWBLOCK_SHIFT + + SECTOR_SHIFT + WPGROUP_SHIFT)) & 0x7); /* Bzzzzzzztt .... Operation complete. */ sd->state = sd_transfer_state; return sd_r1b; @@ -1027,8 +1034,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, } sd->state = sd_programming_state; - sd->wp_groups[addr >> (HWBLOCK_SHIFT + - SECTOR_SHIFT + WPGROUP_SHIFT)] = 0; + sd->wp_groups[addr >> (HWBLOCK_SHIFT + SECTOR_SHIFT + + WPGROUP_SHIFT + 3)] &= ~(1 << ((addr >> (HWBLOCK_SHIFT + + SECTOR_SHIFT + WPGROUP_SHIFT)) & 0x7)); /* Bzzzzzzztt .... Operation complete. */ sd->state = sd_transfer_state; return sd_r1b; -- 1.7.4.1