From nobody Sun Feb 8 12:19:25 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=fb.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1656356370222909.5260485205408; Mon, 27 Jun 2022 11:59:30 -0700 (PDT) Received: from localhost ([::1]:36922 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o5txJ-0002Ig-7q for importer@patchew.org; Mon, 27 Jun 2022 14:59:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57594) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o5tr0-0005NI-Di; Mon, 27 Jun 2022 14:52:58 -0400 Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:13508) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o5tqw-00086B-M1; Mon, 27 Jun 2022 14:52:57 -0400 Received: from pps.filterd (m0044010.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 25RIjfFG017296; Mon, 27 Jun 2022 11:52:44 -0700 Received: from maileast.thefacebook.com ([163.114.130.16]) by mx0a-00082601.pphosted.com (PPS) with ESMTPS id 3gwwpqd55c-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Mon, 27 Jun 2022 11:52:44 -0700 Received: from localhost (2620:10d:c0a8:1b::d) by mail.thefacebook.com (2620:10d:c0a8:83::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.28; Mon, 27 Jun 2022 11:52:42 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fb.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=facebook; bh=VNJ9VKKP6H2aflksewl2BVof8DbdMLxJhTiC/QPWbjM=; b=p94bGBIXnbE5T6An8HNKAxu6y/bvCghJ7tznyswlRtoj9VpQtVqjisyVIeuKi9nyZoxp NMLub7iIrnjTat4G7lECHPwl09ofCNycCoLB+7kh9kcOYA+5KJxY8wW4remanvrtjEOj nLSt9w7APg6u1tktPkL8HedT49qPv8o0eKI= From: Iris Chen To: CC: , , , , , , , , , , , , , , , , Subject: [PATCH 1/2] hw: m25p80: Add Block Protect and Top Bottom bits for write protect Date: Mon, 27 Jun 2022 11:52:33 -0700 Message-ID: <20220627185234.1911337-2-irischenlj@fb.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220627185234.1911337-1-irischenlj@fb.com> References: <20220627185234.1911337-1-irischenlj@fb.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [2620:10d:c0a8:1b::d] X-Proofpoint-ORIG-GUID: C7iu7dfcGTQSmftmdPOkLd6BIn4-DzPl X-Proofpoint-GUID: C7iu7dfcGTQSmftmdPOkLd6BIn4-DzPl X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.883,Hydra:6.0.517,FMLib:17.11.122.1 definitions=2022-06-27_06,2022-06-24_01,2022-06-22_01 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=67.231.145.42; envelope-from=prvs=7177cd4fe2=irischenlj@fb.com; helo=mx0a-00082601.pphosted.com X-Spam_score_int: -21 X-Spam_score: -2.2 X-Spam_bar: -- X-Spam_report: (-2.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.082, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @fb.com) X-ZM-MESSAGEID: 1656356370972100001 Content-Type: text/plain; charset="utf-8" Signed-off-by: Iris Chen Reviewed-by: C=C3=A9dric Le Goater --- hw/block/m25p80.c | 74 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 12 deletions(-) diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c index 50b523e5b1..0156a70f5e 100644 --- a/hw/block/m25p80.c +++ b/hw/block/m25p80.c @@ -38,21 +38,19 @@ #include "trace.h" #include "qom/object.h" =20 -/* Fields for FlashPartInfo->flags */ - -/* erase capabilities */ -#define ER_4K 1 -#define ER_32K 2 -/* set to allow the page program command to write 0s back to 1. Useful for - * modelling EEPROM with SPI flash command set - */ -#define EEPROM 0x100 - /* 16 MiB max in 3 byte address mode */ #define MAX_3BYTES_SIZE 0x1000000 - #define SPI_NOR_MAX_ID_LEN 6 =20 +/* Fields for FlashPartInfo->flags */ +enum spi_nor_option_flags { + ER_4K =3D BIT(0), + ER_32K =3D BIT(1), + EEPROM =3D BIT(2), + SNOR_F_HAS_SR_TB =3D BIT(3), + SNOR_F_HAS_SR_BP3_BIT6 =3D BIT(4), +}; + typedef struct FlashPartInfo { const char *part_name; /* @@ -253,7 +251,8 @@ static const FlashPartInfo known_devices[] =3D { { INFO("n25q512a11", 0x20bb20, 0, 64 << 10, 1024, ER_4K) }, { INFO("n25q512a13", 0x20ba20, 0, 64 << 10, 1024, ER_4K) }, { INFO("n25q128", 0x20ba18, 0, 64 << 10, 256, 0) }, - { INFO("n25q256a", 0x20ba19, 0, 64 << 10, 512, ER_4K) }, + { INFO("n25q256a", 0x20ba19, 0, 64 << 10, 512, + ER_4K | SNOR_F_HAS_SR_BP3_BIT6 | SNOR_F_HAS_SR_TB) }, { INFO("n25q512a", 0x20ba20, 0, 64 << 10, 1024, ER_4K) }, { INFO("n25q512ax3", 0x20ba20, 0x1000, 64 << 10, 1024, ER_4K) }, { INFO("mt25ql512ab", 0x20ba20, 0x1044, 64 << 10, 1024, ER_4K | ER_32K= ) }, @@ -480,6 +479,11 @@ struct Flash { bool reset_enable; bool quad_enable; bool aai_enable; + bool block_protect0; + bool block_protect1; + bool block_protect2; + bool block_protect3; + bool top_bottom_bit; bool status_register_write_disabled; uint8_t ear; =20 @@ -630,6 +634,29 @@ void flash_write8(Flash *s, uint32_t addr, uint8_t dat= a) qemu_log_mask(LOG_GUEST_ERROR, "M25P80: write with write protect!\= n"); return; } + uint32_t block_protect_value =3D (s->block_protect3 << 3) | + (s->block_protect2 << 2) | + (s->block_protect1 << 1) | + (s->block_protect0 << 0); + + uint32_t num_protected_sectors =3D 1 << (block_protect_value - 1); + uint32_t sector =3D addr / s->pi->sector_size; + + /* top_bottom_bit =3D=3D 0 means TOP */ + if (!s->top_bottom_bit) { + if (block_protect_value > 0 && + s->pi->n_sectors <=3D sector + num_protected_sectors) { + qemu_log_mask(LOG_GUEST_ERROR, + "M25P80: write with write protect!\n"); + return; + } + } else { + if (block_protect_value > 0 && sector < num_protected_sectors) { + qemu_log_mask(LOG_GUEST_ERROR, + "M25P80: write with write protect!\n"); + return; + } + } =20 if ((prev ^ data) & data) { trace_m25p80_programming_zero_to_one(s, addr, prev, data); @@ -728,6 +755,15 @@ static void complete_collecting_data(Flash *s) break; case WRSR: s->status_register_write_disabled =3D extract32(s->data[0], 7, 1); + s->block_protect0 =3D extract32(s->data[0], 2, 1); + s->block_protect1 =3D extract32(s->data[0], 3, 1); + s->block_protect2 =3D extract32(s->data[0], 4, 1); + if (s->pi->flags & SNOR_F_HAS_SR_TB) { + s->top_bottom_bit =3D extract32(s->data[0], 5, 1); + } + if (s->pi->flags & SNOR_F_HAS_SR_BP3_BIT6) { + s->block_protect3 =3D extract32(s->data[0], 6, 1); + } =20 switch (get_man(s)) { case MAN_SPANSION: @@ -1213,6 +1249,15 @@ static void decode_new_cmd(Flash *s, uint32_t value) case RDSR: s->data[0] =3D (!!s->write_enable) << 1; s->data[0] |=3D (!!s->status_register_write_disabled) << 7; + s->data[0] |=3D (!!s->block_protect0) << 2; + s->data[0] |=3D (!!s->block_protect1) << 3; + s->data[0] |=3D (!!s->block_protect2) << 4; + if (s->pi->flags & SNOR_F_HAS_SR_TB) { + s->data[0] |=3D (!!s->top_bottom_bit) << 5; + } + if (s->pi->flags & SNOR_F_HAS_SR_BP3_BIT6) { + s->data[0] |=3D (!!s->block_protect3) << 6; + } =20 if (get_man(s) =3D=3D MAN_MACRONIX || get_man(s) =3D=3D MAN_ISSI) { s->data[0] |=3D (!!s->quad_enable) << 6; @@ -1553,6 +1598,11 @@ static void m25p80_reset(DeviceState *d) =20 s->wp_level =3D true; s->status_register_write_disabled =3D false; + s->block_protect0 =3D false; + s->block_protect1 =3D false; + s->block_protect2 =3D false; + s->block_protect3 =3D false; + s->top_bottom_bit =3D false; =20 reset_memory(s); } --=20 2.30.2 From nobody Sun Feb 8 12:19:25 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=fb.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1656356160786423.198779879314; Mon, 27 Jun 2022 11:56:00 -0700 (PDT) Received: from localhost ([::1]:60766 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o5ttv-0007X2-3L for importer@patchew.org; Mon, 27 Jun 2022 14:55:59 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57596) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o5tr0-0005NJ-Df; Mon, 27 Jun 2022 14:52:58 -0400 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:51652) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o5tqx-00086N-Pq; Mon, 27 Jun 2022 14:52:58 -0400 Received: from pps.filterd (m0109332.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 25RIop47022385; Mon, 27 Jun 2022 11:52:49 -0700 Received: from maileast.thefacebook.com ([163.114.130.16]) by mx0a-00082601.pphosted.com (PPS) with ESMTPS id 3gx03yvfx6-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Mon, 27 Jun 2022 11:52:48 -0700 Received: from localhost (2620:10d:c0a8:1b::d) by mail.thefacebook.com (2620:10d:c0a8:83::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.28; Mon, 27 Jun 2022 11:52:47 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fb.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=facebook; bh=fOdg8UnAn685nAVOgHD+D15AIIRQFhzcWx8eDoER38I=; b=pynTP6cfq2i6T11E7Fdo4Ejz6ro8a15dfBBeObA3NeoLehRzNMgubQ9swUiqyJ0lCDXF hZYhQGq0W/RlqQ80THiViWQx9s4k7RFOCpsrBm2oplVBNH7rsjxCHoYDUXsrTbognT8T M2hfgUTZZBGcZlwYPYUfqvP9+am2eqoo6ew= From: Iris Chen To: CC: , , , , , , , , , , , , , , , , Subject: [PATCH 2/2] hw: m25p80: add tests for BP and TB bit write protect Date: Mon, 27 Jun 2022 11:52:34 -0700 Message-ID: <20220627185234.1911337-3-irischenlj@fb.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220627185234.1911337-1-irischenlj@fb.com> References: <20220627185234.1911337-1-irischenlj@fb.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [2620:10d:c0a8:1b::d] X-Proofpoint-GUID: zi3d0TC1ByA3KT-3i7BdyiYbBgUFE1RK X-Proofpoint-ORIG-GUID: zi3d0TC1ByA3KT-3i7BdyiYbBgUFE1RK X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.883,Hydra:6.0.517,FMLib:17.11.122.1 definitions=2022-06-27_06,2022-06-24_01,2022-06-22_01 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=67.231.153.30; envelope-from=prvs=7177cd4fe2=irischenlj@fb.com; helo=mx0b-00082601.pphosted.com X-Spam_score_int: -21 X-Spam_score: -2.2 X-Spam_bar: -- X-Spam_report: (-2.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.082, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @fb.com) X-ZM-MESSAGEID: 1656356161625100001 Content-Type: text/plain; charset="utf-8" Signed-off-by: Iris Chen Reviewed-by: C=C3=A9dric Le Goater --- tests/qtest/aspeed_smc-test.c | 111 ++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/tests/qtest/aspeed_smc-test.c b/tests/qtest/aspeed_smc-test.c index 1258687eac..05ce941566 100644 --- a/tests/qtest/aspeed_smc-test.c +++ b/tests/qtest/aspeed_smc-test.c @@ -192,6 +192,24 @@ static void read_page_mem(uint32_t addr, uint32_t *pag= e) } } =20 +static void write_page_mem(uint32_t addr, uint32_t write_value) +{ + spi_ctrl_setmode(CTRL_WRITEMODE, PP); + + for (int i =3D 0; i < FLASH_PAGE_SIZE / 4; i++) { + writel(ASPEED_FLASH_BASE + addr + i * 4, write_value); + } +} + +static void assert_page_mem(uint32_t addr, uint32_t expected_value) +{ + uint32_t page[FLASH_PAGE_SIZE / 4]; + read_page_mem(addr, page); + for (int i =3D 0; i < FLASH_PAGE_SIZE / 4; i++) { + g_assert_cmphex(page[i], =3D=3D, expected_value); + } +} + static void test_erase_sector(void) { uint32_t some_page_addr =3D 0x600 * FLASH_PAGE_SIZE; @@ -501,6 +519,95 @@ static void test_status_reg_write_protection(void) flash_reset(); } =20 +static void test_write_block_protect(void) +{ + uint32_t sector_size =3D 65536; + uint32_t n_sectors =3D 512; + + spi_ce_ctrl(1 << CRTL_EXTENDED0); + spi_conf(CONF_ENABLE_W0); + + uint32_t bp_bits =3D 0b0; + + for (int i =3D 0; i < 16; i++) { + bp_bits =3D ((i & 0b1000) << 3) | ((i & 0b0111) << 2); + + spi_ctrl_start_user(); + writeb(ASPEED_FLASH_BASE, WREN); + writeb(ASPEED_FLASH_BASE, BULK_ERASE); + writeb(ASPEED_FLASH_BASE, WREN); + writeb(ASPEED_FLASH_BASE, WRSR); + writeb(ASPEED_FLASH_BASE, bp_bits); + writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); + writeb(ASPEED_FLASH_BASE, WREN); + spi_ctrl_stop_user(); + + uint32_t num_protected_sectors =3D i ? MIN(1 << (i - 1), n_sectors= ) : 0; + uint32_t protection_start =3D n_sectors - num_protected_sectors; + uint32_t protection_end =3D n_sectors; + + for (int sector =3D 0; sector < n_sectors; sector++) { + uint32_t addr =3D sector * sector_size; + + assert_page_mem(addr, 0xffffffff); + write_page_mem(addr, make_be32(0xabcdef12)); + + uint32_t expected_value =3D protection_start <=3D sector + && sector < protection_end + ? 0xffffffff : 0xabcdef12; + + assert_page_mem(addr, expected_value); + } + } + + flash_reset(); +} + +static void test_write_block_protect_bottom_bit(void) +{ + uint32_t sector_size =3D 65536; + uint32_t n_sectors =3D 512; + + spi_ce_ctrl(1 << CRTL_EXTENDED0); + spi_conf(CONF_ENABLE_W0); + + /* top bottom bit is enabled */ + uint32_t bp_bits =3D 0b00100 << 3; + + for (int i =3D 0; i < 16; i++) { + bp_bits =3D (((i & 0b1000) | 0b0100) << 3) | ((i & 0b0111) << 2); + + spi_ctrl_start_user(); + writeb(ASPEED_FLASH_BASE, WREN); + writeb(ASPEED_FLASH_BASE, BULK_ERASE); + writeb(ASPEED_FLASH_BASE, WREN); + writeb(ASPEED_FLASH_BASE, WRSR); + writeb(ASPEED_FLASH_BASE, bp_bits); + writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR); + writeb(ASPEED_FLASH_BASE, WREN); + spi_ctrl_stop_user(); + + uint32_t num_protected_sectors =3D i ? MIN(1 << (i - 1), n_sectors= ) : 0; + uint32_t protection_start =3D 0; + uint32_t protection_end =3D num_protected_sectors; + + for (int sector =3D 0; sector < n_sectors; sector++) { + uint32_t addr =3D sector * sector_size; + + assert_page_mem(addr, 0xffffffff); + write_page_mem(addr, make_be32(0xabcdef12)); + + uint32_t expected_value =3D protection_start <=3D sector + && sector < protection_end + ? 0xffffffff : 0xabcdef12; + + assert_page_mem(addr, expected_value); + } + } + + flash_reset(); +} + static char tmp_path[] =3D "/tmp/qtest.m25p80.XXXXXX"; =20 int main(int argc, char **argv) @@ -529,6 +636,10 @@ int main(int argc, char **argv) qtest_add_func("/ast2400/smc/read_status_reg", test_read_status_reg); qtest_add_func("/ast2400/smc/status_reg_write_protection", test_status_reg_write_protection); + qtest_add_func("/ast2400/smc/write_block_protect", + test_write_block_protect); + qtest_add_func("/ast2400/smc/write_block_protect_bottom_bit", + test_write_block_protect_bottom_bit); =20 flash_reset(); ret =3D g_test_run(); --=20 2.30.2 From nobody Sun Feb 8 12:19:25 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=fb.com ARC-Seal: i=1; a=rsa-sha256; t=1657301819; cv=none; d=zohomail.com; s=zohoarc; b=OvUW/OhBr9fpKGkUJaAbXerC84R1fpXS6mgLKbfayOhP6Nr5fWjdk+93/e2QSo+qyvuULDEYIw/QB9DA7SFNaiBq5fKSMnDb/bgCFbf2iMiE36XkQjZTZxcvFRbHiF5ZP2Bsp0YCTeoBP3Ny01O/ntFhyXKEDaepigYwVLr9jQ4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1657301819; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject; bh=p9odgMFQVS6eEY1Gg3Dw2pe3XQ7rqLYMCNrXMb8STH4=; b=SZGMhpuHaQyKLbwrwDytJsjqcwx7LxsSd8pkTav2RfifEQDFxA0SwvU+3SUAPolmWO7RLZiS/c1LIgFoqEeztv0XIS65HvWg8oJqgfJmChsZEDucqDULwZDSC25AoxyjsuiWt+S2EaIkBCUstoyubB9th1IPZfEabpyqjYUKrOo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1657301819917957.2361315206966; Fri, 8 Jul 2022 10:36:59 -0700 (PDT) Received: from localhost ([::1]:38462 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o9ruU-0005Qr-1b for importer@patchew.org; Fri, 08 Jul 2022 13:36:58 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57160) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o9r7P-0006fX-BP; Fri, 08 Jul 2022 12:46:16 -0400 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:21296) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o9r7M-00081J-N6; Fri, 08 Jul 2022 12:46:14 -0400 Received: from pps.filterd (m0109331.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 268Csr6Z024591; Fri, 8 Jul 2022 09:45:58 -0700 Received: from maileast.thefacebook.com ([163.114.130.16]) by mx0a-00082601.pphosted.com (PPS) with ESMTPS id 3h624uqyqc-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Fri, 08 Jul 2022 09:45:57 -0700 Received: from localhost (2620:10d:c0a8:1b::d) by mail.thefacebook.com (2620:10d:c0a8:83::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.28; Fri, 8 Jul 2022 09:45:56 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fb.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=facebook; bh=p9odgMFQVS6eEY1Gg3Dw2pe3XQ7rqLYMCNrXMb8STH4=; b=ImTpjtuLZuUWkGIbn1bhVZTP5ud+EGP+l9t2QIqWiwPxMW4kXBcPrvFMdr28xITXO/ZS lw1aOhe9fK/sdzfSTk8ZFhfRmOJW8u5EYBNxzySeAb756ONQrumsvD6M8zpY4ZsxZPXS l7gcJcmNxBoZX68uYzepCI3tU6iEdIa6O64= From: Iris Chen To: CC: , , , , , , , , , , , , , , , , Subject: [PATCH v3] hw: m25p80: Add Block Protect and Top Bottom bits for write protect Date: Fri, 8 Jul 2022 09:45:52 -0700 Message-ID: <20220708164552.3462620-1-irischenlj@fb.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220627185234.1911337-1-irischenlj@fb.com> References: <20220627185234.1911337-1-irischenlj@fb.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [2620:10d:c0a8:1b::d] X-Proofpoint-GUID: v3yMS-q7J_PPqhgqFHrrq9c8wPIJQ6tF X-Proofpoint-ORIG-GUID: v3yMS-q7J_PPqhgqFHrrq9c8wPIJQ6tF X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.883,Hydra:6.0.517,FMLib:17.11.122.1 definitions=2022-07-08_14,2022-07-08_01,2022-06-22_01 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=67.231.153.30; envelope-from=prvs=8188451133=irischenlj@fb.com; helo=mx0b-00082601.pphosted.com X-Spam_score_int: -21 X-Spam_score: -2.2 X-Spam_bar: -- X-Spam_report: (-2.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.082, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @fb.com) X-ZM-MESSAGEID: 1657301821290100001 Content-Type: text/plain; charset="utf-8" Signed-off-by: Iris Chen Reviewed-by: Francisco Iglesias --- Cosmetic suggestions addressed.=20 hw/block/m25p80.c | 102 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 90 insertions(+), 12 deletions(-) diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c index 50b523e5b1..f3b401cf90 100644 --- a/hw/block/m25p80.c +++ b/hw/block/m25p80.c @@ -38,21 +38,19 @@ #include "trace.h" #include "qom/object.h" =20 -/* Fields for FlashPartInfo->flags */ - -/* erase capabilities */ -#define ER_4K 1 -#define ER_32K 2 -/* set to allow the page program command to write 0s back to 1. Useful for - * modelling EEPROM with SPI flash command set - */ -#define EEPROM 0x100 - /* 16 MiB max in 3 byte address mode */ #define MAX_3BYTES_SIZE 0x1000000 - #define SPI_NOR_MAX_ID_LEN 6 =20 +/* Fields for FlashPartInfo->flags */ +enum spi_flash_option_flags { + ER_4K =3D BIT(0), + ER_32K =3D BIT(1), + EEPROM =3D BIT(2), + HAS_SR_TB =3D BIT(3), + HAS_SR_BP3_BIT6 =3D BIT(4), +}; + typedef struct FlashPartInfo { const char *part_name; /* @@ -253,7 +251,8 @@ static const FlashPartInfo known_devices[] =3D { { INFO("n25q512a11", 0x20bb20, 0, 64 << 10, 1024, ER_4K) }, { INFO("n25q512a13", 0x20ba20, 0, 64 << 10, 1024, ER_4K) }, { INFO("n25q128", 0x20ba18, 0, 64 << 10, 256, 0) }, - { INFO("n25q256a", 0x20ba19, 0, 64 << 10, 512, ER_4K) }, + { INFO("n25q256a", 0x20ba19, 0, 64 << 10, 512, + ER_4K | HAS_SR_BP3_BIT6 | HAS_SR_TB) }, { INFO("n25q512a", 0x20ba20, 0, 64 << 10, 1024, ER_4K) }, { INFO("n25q512ax3", 0x20ba20, 0x1000, 64 << 10, 1024, ER_4K) }, { INFO("mt25ql512ab", 0x20ba20, 0x1044, 64 << 10, 1024, ER_4K | ER_32K= ) }, @@ -480,6 +479,11 @@ struct Flash { bool reset_enable; bool quad_enable; bool aai_enable; + bool block_protect0; + bool block_protect1; + bool block_protect2; + bool block_protect3; + bool top_bottom_bit; bool status_register_write_disabled; uint8_t ear; =20 @@ -625,12 +629,36 @@ void flash_write8(Flash *s, uint32_t addr, uint8_t da= ta) { uint32_t page =3D addr / s->pi->page_size; uint8_t prev =3D s->storage[s->cur_addr]; + uint32_t block_protect_value =3D (s->block_protect3 << 3) | + (s->block_protect2 << 2) | + (s->block_protect1 << 1) | + (s->block_protect0 << 0); =20 if (!s->write_enable) { qemu_log_mask(LOG_GUEST_ERROR, "M25P80: write with write protect!\= n"); return; } =20 + if (block_protect_value > 0) { + uint32_t num_protected_sectors =3D 1 << (block_protect_value - 1); + uint32_t sector =3D addr / s->pi->sector_size; + + /* top_bottom_bit =3D=3D 0 means TOP */ + if (!s->top_bottom_bit) { + if (s->pi->n_sectors <=3D sector + num_protected_sectors) { + qemu_log_mask(LOG_GUEST_ERROR, + "M25P80: write with write protect!\n"); + return; + } + } else { + if (sector < num_protected_sectors) { + qemu_log_mask(LOG_GUEST_ERROR, + "M25P80: write with write protect!\n"); + return; + } + } + } + if ((prev ^ data) & data) { trace_m25p80_programming_zero_to_one(s, addr, prev, data); } @@ -728,6 +756,15 @@ static void complete_collecting_data(Flash *s) break; case WRSR: s->status_register_write_disabled =3D extract32(s->data[0], 7, 1); + s->block_protect0 =3D extract32(s->data[0], 2, 1); + s->block_protect1 =3D extract32(s->data[0], 3, 1); + s->block_protect2 =3D extract32(s->data[0], 4, 1); + if (s->pi->flags & HAS_SR_TB) { + s->top_bottom_bit =3D extract32(s->data[0], 5, 1); + } + if (s->pi->flags & HAS_SR_BP3_BIT6) { + s->block_protect3 =3D extract32(s->data[0], 6, 1); + } =20 switch (get_man(s)) { case MAN_SPANSION: @@ -1213,6 +1250,15 @@ static void decode_new_cmd(Flash *s, uint32_t value) case RDSR: s->data[0] =3D (!!s->write_enable) << 1; s->data[0] |=3D (!!s->status_register_write_disabled) << 7; + s->data[0] |=3D (!!s->block_protect0) << 2; + s->data[0] |=3D (!!s->block_protect1) << 3; + s->data[0] |=3D (!!s->block_protect2) << 4; + if (s->pi->flags & HAS_SR_TB) { + s->data[0] |=3D (!!s->top_bottom_bit) << 5; + } + if (s->pi->flags & HAS_SR_BP3_BIT6) { + s->data[0] |=3D (!!s->block_protect3) << 6; + } =20 if (get_man(s) =3D=3D MAN_MACRONIX || get_man(s) =3D=3D MAN_ISSI) { s->data[0] |=3D (!!s->quad_enable) << 6; @@ -1553,6 +1599,11 @@ static void m25p80_reset(DeviceState *d) =20 s->wp_level =3D true; s->status_register_write_disabled =3D false; + s->block_protect0 =3D false; + s->block_protect1 =3D false; + s->block_protect2 =3D false; + s->block_protect3 =3D false; + s->top_bottom_bit =3D false; =20 reset_memory(s); } @@ -1639,6 +1690,32 @@ static const VMStateDescription vmstate_m25p80_write= _protect =3D { } }; =20 +static bool m25p80_block_protect_needed(void *opaque) +{ + Flash *s =3D (Flash *)opaque; + + return s->block_protect0 || + s->block_protect1 || + s->block_protect2 || + s->block_protect3 || + s->top_bottom_bit; +} + +static const VMStateDescription vmstate_m25p80_block_protect =3D { + .name =3D "m25p80/block_protect", + .version_id =3D 1, + .minimum_version_id =3D 1, + .needed =3D m25p80_block_protect_needed, + .fields =3D (VMStateField[]) { + VMSTATE_BOOL(block_protect0, Flash), + VMSTATE_BOOL(block_protect1, Flash), + VMSTATE_BOOL(block_protect2, Flash), + VMSTATE_BOOL(block_protect3, Flash), + VMSTATE_BOOL(top_bottom_bit, Flash), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_m25p80 =3D { .name =3D "m25p80", .version_id =3D 0, @@ -1671,6 +1748,7 @@ static const VMStateDescription vmstate_m25p80 =3D { &vmstate_m25p80_data_read_loop, &vmstate_m25p80_aai_enable, &vmstate_m25p80_write_protect, + &vmstate_m25p80_block_protect, NULL } }; --=20 2.30.2 From nobody Sun Feb 8 12:19:25 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=fb.com ARC-Seal: i=1; a=rsa-sha256; t=1657160315; cv=none; d=zohomail.com; s=zohoarc; b=bSQDZGOWgnObIb1CG1ztaPqy7Ogyehq+Zc0WQ3F4/AhsIo4H4HiY85Kcm0HokBqJJ61pohIpA+vInW3VedDbn56f3Zh+bPz4Wp06Nq/cnU6Aa2Hxi7Vs2FKdeBujXkhGtiEa5ioeDPu3KpuchOyz50LtLSNhiOu30A1siR/t8QU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1657160315; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject; bh=3070Y4J7B6E4ebAzjovpyAX6FIkhzbPFyiS/r0Kai1U=; b=WuOopVA6/8VAWzt0HNDPLewovywpXhAp4QND+jLwlHYm+GkbT0hGhX7F1+FHBHMDmzDPjz9bLFQvBs93BKyoMt5RCtXphPGIwfn+S8RDgHSi/agfwt4k6PPzjj637Y/Pb35jYC0okQoc5BFiBI6HMhyXjXFO6wzejsMVW78nf5o= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1657160315235853.4651461375594; Wed, 6 Jul 2022 19:18:35 -0700 (PDT) Received: from localhost ([::1]:55992 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o9H69-0002G6-Bl for importer@patchew.org; Wed, 06 Jul 2022 22:18:33 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:47010) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o9H4W-0001Ex-3F; Wed, 06 Jul 2022 22:16:52 -0400 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:43236) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o9H4R-0005Wa-T4; Wed, 06 Jul 2022 22:16:51 -0400 Received: from pps.filterd (m0148460.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 266L6v7N029040; Wed, 6 Jul 2022 19:16:31 -0700 Received: from maileast.thefacebook.com ([163.114.130.16]) by mx0a-00082601.pphosted.com (PPS) with ESMTPS id 3h4ucmac5h-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Wed, 06 Jul 2022 19:16:31 -0700 Received: from localhost (2620:10d:c0a8:1b::d) by mail.thefacebook.com (2620:10d:c0a8:83::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.28; Wed, 6 Jul 2022 19:16:30 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fb.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=facebook; bh=3070Y4J7B6E4ebAzjovpyAX6FIkhzbPFyiS/r0Kai1U=; b=PuofVdc1NWCPMDEwm2r60nCSM1km58hEC19ggqfvmNBQ51EWrfVLWrDxpVttALJQQxoM uI/+UGN+8A+HLEw9QaOMvB7fDYLcHR4Chh3I++BomQ0KiimCgiWwBOoO/dK95CE+dayt OIKD/l8/lisIAtg9abhhx7oweCqhX2GgX9A= From: Iris Chen To: CC: , , , , , , , , , , , , , , , , Subject: [PATCH v2] hw: m25p80: Add Block Protect and Top Bottom bits for write protect Date: Wed, 6 Jul 2022 19:16:26 -0700 Message-ID: <20220707021626.2482219-1-irischenlj@fb.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220627185234.1911337-1-irischenlj@fb.com> References: <20220627185234.1911337-1-irischenlj@fb.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [2620:10d:c0a8:1b::d] X-Proofpoint-GUID: VBxGL_7BAGcCp5Se0CjsbHmTpRfcV5aV X-Proofpoint-ORIG-GUID: VBxGL_7BAGcCp5Se0CjsbHmTpRfcV5aV X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.883,Hydra:6.0.517,FMLib:17.11.122.1 definitions=2022-07-06_14,2022-06-28_01,2022-06-22_01 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=67.231.153.30; envelope-from=prvs=81874fe792=irischenlj@fb.com; helo=mx0b-00082601.pphosted.com X-Spam_score_int: -21 X-Spam_score: -2.2 X-Spam_bar: -- X-Spam_report: (-2.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.082, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @fb.com) X-ZM-MESSAGEID: 1657160317722100001 Content-Type: text/plain; charset="utf-8" Signed-off-by: Iris Chen Reviewed-by: Francisco Iglesias --- Addressing all comments.=20 In reponse to this comment: "Something wrong will occur if all block_protect[0123] are zeroes", the code actually ignores num_protected_sectors when block_protect_value = =3D 0 which happens when block_protect[0123] are zeroes. =20 You can refer to the bottom block in v1, where we only look at cases when=20 block_protect_value > 0 so it is actually handled. Regardless, since we were setting num_protected_sectors in either case, I have refactored the code to make it more clear.=20 hw/block/m25p80.c | 103 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 91 insertions(+), 12 deletions(-) diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c index 50b523e5b1..bddea9853b 100644 --- a/hw/block/m25p80.c +++ b/hw/block/m25p80.c @@ -38,21 +38,19 @@ #include "trace.h" #include "qom/object.h" =20 -/* Fields for FlashPartInfo->flags */ - -/* erase capabilities */ -#define ER_4K 1 -#define ER_32K 2 -/* set to allow the page program command to write 0s back to 1. Useful for - * modelling EEPROM with SPI flash command set - */ -#define EEPROM 0x100 - /* 16 MiB max in 3 byte address mode */ #define MAX_3BYTES_SIZE 0x1000000 - #define SPI_NOR_MAX_ID_LEN 6 =20 +/* Fields for FlashPartInfo->flags */ +enum spi_option_flags { + ER_4K =3D BIT(0), + ER_32K =3D BIT(1), + EEPROM =3D BIT(2), + HAS_SR_TB =3D BIT(3), + HAS_SR_BP3_BIT6 =3D BIT(4), +}; + typedef struct FlashPartInfo { const char *part_name; /* @@ -253,7 +251,8 @@ static const FlashPartInfo known_devices[] =3D { { INFO("n25q512a11", 0x20bb20, 0, 64 << 10, 1024, ER_4K) }, { INFO("n25q512a13", 0x20ba20, 0, 64 << 10, 1024, ER_4K) }, { INFO("n25q128", 0x20ba18, 0, 64 << 10, 256, 0) }, - { INFO("n25q256a", 0x20ba19, 0, 64 << 10, 512, ER_4K) }, + { INFO("n25q256a", 0x20ba19, 0, 64 << 10, 512, + ER_4K | HAS_SR_BP3_BIT6 | HAS_SR_TB) }, { INFO("n25q512a", 0x20ba20, 0, 64 << 10, 1024, ER_4K) }, { INFO("n25q512ax3", 0x20ba20, 0x1000, 64 << 10, 1024, ER_4K) }, { INFO("mt25ql512ab", 0x20ba20, 0x1044, 64 << 10, 1024, ER_4K | ER_32K= ) }, @@ -480,6 +479,11 @@ struct Flash { bool reset_enable; bool quad_enable; bool aai_enable; + bool block_protect0; + bool block_protect1; + bool block_protect2; + bool block_protect3; + bool top_bottom_bit; bool status_register_write_disabled; uint8_t ear; =20 @@ -626,11 +630,36 @@ void flash_write8(Flash *s, uint32_t addr, uint8_t da= ta) uint32_t page =3D addr / s->pi->page_size; uint8_t prev =3D s->storage[s->cur_addr]; =20 + uint32_t block_protect_value =3D (s->block_protect3 << 3) | + (s->block_protect2 << 2) | + (s->block_protect1 << 1) | + (s->block_protect0 << 0); + if (!s->write_enable) { qemu_log_mask(LOG_GUEST_ERROR, "M25P80: write with write protect!\= n"); return; } =20 + if (block_protect_value > 0) { + uint32_t num_protected_sectors =3D 1 << (block_protect_value - 1); + uint32_t sector =3D addr / s->pi->sector_size; + + /* top_bottom_bit =3D=3D 0 means TOP */ + if (!s->top_bottom_bit) { + if (s->pi->n_sectors <=3D sector + num_protected_sectors) { + qemu_log_mask(LOG_GUEST_ERROR, + "M25P80: write with write protect!\n"); + return; + } + } else { + if (sector < num_protected_sectors) { + qemu_log_mask(LOG_GUEST_ERROR, + "M25P80: write with write protect!\n"); + return; + } + } + } + if ((prev ^ data) & data) { trace_m25p80_programming_zero_to_one(s, addr, prev, data); } @@ -728,6 +757,15 @@ static void complete_collecting_data(Flash *s) break; case WRSR: s->status_register_write_disabled =3D extract32(s->data[0], 7, 1); + s->block_protect0 =3D extract32(s->data[0], 2, 1); + s->block_protect1 =3D extract32(s->data[0], 3, 1); + s->block_protect2 =3D extract32(s->data[0], 4, 1); + if (s->pi->flags & HAS_SR_TB) { + s->top_bottom_bit =3D extract32(s->data[0], 5, 1); + } + if (s->pi->flags & HAS_SR_BP3_BIT6) { + s->block_protect3 =3D extract32(s->data[0], 6, 1); + } =20 switch (get_man(s)) { case MAN_SPANSION: @@ -1213,6 +1251,15 @@ static void decode_new_cmd(Flash *s, uint32_t value) case RDSR: s->data[0] =3D (!!s->write_enable) << 1; s->data[0] |=3D (!!s->status_register_write_disabled) << 7; + s->data[0] |=3D (!!s->block_protect0) << 2; + s->data[0] |=3D (!!s->block_protect1) << 3; + s->data[0] |=3D (!!s->block_protect2) << 4; + if (s->pi->flags & HAS_SR_TB) { + s->data[0] |=3D (!!s->top_bottom_bit) << 5; + } + if (s->pi->flags & HAS_SR_BP3_BIT6) { + s->data[0] |=3D (!!s->block_protect3) << 6; + } =20 if (get_man(s) =3D=3D MAN_MACRONIX || get_man(s) =3D=3D MAN_ISSI) { s->data[0] |=3D (!!s->quad_enable) << 6; @@ -1553,6 +1600,11 @@ static void m25p80_reset(DeviceState *d) =20 s->wp_level =3D true; s->status_register_write_disabled =3D false; + s->block_protect0 =3D false; + s->block_protect1 =3D false; + s->block_protect2 =3D false; + s->block_protect3 =3D false; + s->top_bottom_bit =3D false; =20 reset_memory(s); } @@ -1639,6 +1691,32 @@ static const VMStateDescription vmstate_m25p80_write= _protect =3D { } }; =20 +static bool m25p80_block_protect_needed(void *opaque) +{ + Flash *s =3D (Flash *)opaque; + + return s->block_protect0 || + s->block_protect1 || + s->block_protect2 || + s->block_protect3 || + s->top_bottom_bit; +} + +static const VMStateDescription vmstate_m25p80_block_protect =3D { + .name =3D "m25p80/block_protect", + .version_id =3D 1, + .minimum_version_id =3D 1, + .needed =3D m25p80_block_protect_needed, + .fields =3D (VMStateField[]) { + VMSTATE_BOOL(block_protect0, Flash), + VMSTATE_BOOL(block_protect1, Flash), + VMSTATE_BOOL(block_protect2, Flash), + VMSTATE_BOOL(block_protect3, Flash), + VMSTATE_BOOL(top_bottom_bit, Flash), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_m25p80 =3D { .name =3D "m25p80", .version_id =3D 0, @@ -1671,6 +1749,7 @@ static const VMStateDescription vmstate_m25p80 =3D { &vmstate_m25p80_data_read_loop, &vmstate_m25p80_aai_enable, &vmstate_m25p80_write_protect, + &vmstate_m25p80_block_protect, NULL } }; --=20 2.30.2