diff mbox series

[2/4] mtd: spi-nor: add advanced protection and security features support

Message ID 20211027103352.8879-3-sshivamurthy@micron.com
State Changes Requested
Delegated to: Ambarus Tudor
Headers show
Series enabling Advanced protection and security features | expand

Commit Message

Shivamurthy Shastri Oct. 27, 2021, 10:33 a.m. UTC
From: Shivamurthy Shastri <sshivamurthy@micron.com>

Added functionalities to support advanced securtiy and protection
features in new SPI NOR flashes.

Signed-off-by: Shivamurthy Shastri <sshivamurthy@micron.com>
---
 drivers/mtd/spi-nor/Makefile     |   2 +-
 drivers/mtd/spi-nor/advprotsec.c | 209 +++++++++++++++++++++++++++++++
 drivers/mtd/spi-nor/core.c       |   2 +
 include/linux/mtd/mtd.h          |  19 +++
 4 files changed, 231 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mtd/spi-nor/advprotsec.c

Comments

kernel test robot Oct. 27, 2021, 9 p.m. UTC | #1
Hi,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on mtd/mtd/next]
[also build test WARNING on mtd/mtd/fixes v5.15-rc7 next-20211027]
[cannot apply to mtd/spi-nor/next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/shiva-linuxworks-gmail-com/enabling-Advanced-protection-and-security-features/20211027-183458
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next
config: arc-randconfig-r043-20211027 (attached as .config)
compiler: arc-elf-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/d26eac1611c4409954b4d0c44215e1a53aa7605a
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review shiva-linuxworks-gmail-com/enabling-Advanced-protection-and-security-features/20211027-183458
        git checkout d26eac1611c4409954b4d0c44215e1a53aa7605a
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=arc 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/mtd/spi-nor/advprotsec.c:192:6: warning: no previous prototype for 'spi_nor_register_security_ops' [-Wmissing-prototypes]
     192 | void spi_nor_register_security_ops(struct spi_nor *nor)
         |      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~


vim +/spi_nor_register_security_ops +192 drivers/mtd/spi-nor/advprotsec.c

   191	
 > 192	void spi_nor_register_security_ops(struct spi_nor *nor)

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
kernel test robot Oct. 27, 2021, 11:01 p.m. UTC | #2
Hi,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on mtd/mtd/next]
[also build test ERROR on mtd/mtd/fixes v5.15-rc7 next-20211027]
[cannot apply to mtd/spi-nor/next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/shiva-linuxworks-gmail-com/enabling-Advanced-protection-and-security-features/20211027-183458
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next
config: i386-randconfig-a002-20211027 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 5db7568a6a1fcb408eb8988abdaff2a225a8eb72)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/d26eac1611c4409954b4d0c44215e1a53aa7605a
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review shiva-linuxworks-gmail-com/enabling-Advanced-protection-and-security-features/20211027-183458
        git checkout d26eac1611c4409954b4d0c44215e1a53aa7605a
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All error/warnings (new ones prefixed by >>):

>> drivers/mtd/spi-nor/core.c:3202:2: error: implicit declaration of function 'spi_nor_register_security_ops' [-Werror,-Wimplicit-function-declaration]
           spi_nor_register_security_ops(nor);
           ^
   drivers/mtd/spi-nor/core.c:3202:2: note: did you mean 'spi_nor_register_locking_ops'?
   drivers/mtd/spi-nor/core.h:572:6: note: 'spi_nor_register_locking_ops' declared here
   void spi_nor_register_locking_ops(struct spi_nor *nor);
        ^
   1 error generated.
--
>> drivers/mtd/spi-nor/advprotsec.c:192:6: warning: no previous prototype for function 'spi_nor_register_security_ops' [-Wmissing-prototypes]
   void spi_nor_register_security_ops(struct spi_nor *nor)
        ^
   drivers/mtd/spi-nor/advprotsec.c:192:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   void spi_nor_register_security_ops(struct spi_nor *nor)
   ^
   static 
   1 warning generated.


vim +/spi_nor_register_security_ops +3202 drivers/mtd/spi-nor/core.c

  3073	
  3074	int spi_nor_scan(struct spi_nor *nor, const char *name,
  3075			 const struct spi_nor_hwcaps *hwcaps)
  3076	{
  3077		const struct flash_info *info;
  3078		struct device *dev = nor->dev;
  3079		struct mtd_info *mtd = &nor->mtd;
  3080		struct device_node *np = spi_nor_get_flash_node(nor);
  3081		int ret;
  3082		int i;
  3083	
  3084		ret = spi_nor_check(nor);
  3085		if (ret)
  3086			return ret;
  3087	
  3088		/* Reset SPI protocol for all commands. */
  3089		nor->reg_proto = SNOR_PROTO_1_1_1;
  3090		nor->read_proto = SNOR_PROTO_1_1_1;
  3091		nor->write_proto = SNOR_PROTO_1_1_1;
  3092	
  3093		/*
  3094		 * We need the bounce buffer early to read/write registers when going
  3095		 * through the spi-mem layer (buffers have to be DMA-able).
  3096		 * For spi-mem drivers, we'll reallocate a new buffer if
  3097		 * nor->page_size turns out to be greater than PAGE_SIZE (which
  3098		 * shouldn't happen before long since NOR pages are usually less
  3099		 * than 1KB) after spi_nor_scan() returns.
  3100		 */
  3101		nor->bouncebuf_size = PAGE_SIZE;
  3102		nor->bouncebuf = devm_kmalloc(dev, nor->bouncebuf_size,
  3103					      GFP_KERNEL);
  3104		if (!nor->bouncebuf)
  3105			return -ENOMEM;
  3106	
  3107		info = spi_nor_get_flash_info(nor, name);
  3108		if (IS_ERR(info))
  3109			return PTR_ERR(info);
  3110	
  3111		nor->info = info;
  3112	
  3113		spi_nor_debugfs_init(nor, info);
  3114	
  3115		mutex_init(&nor->lock);
  3116	
  3117		/*
  3118		 * Make sure the XSR_RDY flag is set before calling
  3119		 * spi_nor_wait_till_ready(). Xilinx S3AN share MFR
  3120		 * with Atmel SPI NOR.
  3121		 */
  3122		if (info->flags & SPI_NOR_XSR_RDY)
  3123			nor->flags |=  SNOR_F_READY_XSR_RDY;
  3124	
  3125		if (info->flags & SPI_NOR_HAS_LOCK)
  3126			nor->flags |= SNOR_F_HAS_LOCK;
  3127	
  3128		mtd->_write = spi_nor_write;
  3129	
  3130		/* Init flash parameters based on flash_info struct and SFDP */
  3131		ret = spi_nor_init_params(nor);
  3132		if (ret)
  3133			return ret;
  3134	
  3135		if (!mtd->name)
  3136			mtd->name = dev_name(dev);
  3137		mtd->priv = nor;
  3138		mtd->type = MTD_NORFLASH;
  3139		mtd->writesize = nor->params->writesize;
  3140		mtd->flags = MTD_CAP_NORFLASH;
  3141		mtd->size = nor->params->size;
  3142		mtd->_erase = spi_nor_erase;
  3143		mtd->_read = spi_nor_read;
  3144		mtd->_suspend = spi_nor_suspend;
  3145		mtd->_resume = spi_nor_resume;
  3146		mtd->_get_device = spi_nor_get_device;
  3147		mtd->_put_device = spi_nor_put_device;
  3148	
  3149		if (info->flags & USE_FSR)
  3150			nor->flags |= SNOR_F_USE_FSR;
  3151		if (info->flags & SPI_NOR_HAS_TB) {
  3152			nor->flags |= SNOR_F_HAS_SR_TB;
  3153			if (info->flags & SPI_NOR_TB_SR_BIT6)
  3154				nor->flags |= SNOR_F_HAS_SR_TB_BIT6;
  3155		}
  3156	
  3157		if (info->flags & NO_CHIP_ERASE)
  3158			nor->flags |= SNOR_F_NO_OP_CHIP_ERASE;
  3159		if (info->flags & USE_CLSR)
  3160			nor->flags |= SNOR_F_USE_CLSR;
  3161		if (info->flags & SPI_NOR_SWP_IS_VOLATILE)
  3162			nor->flags |= SNOR_F_SWP_IS_VOLATILE;
  3163	
  3164		if (info->flags & SPI_NOR_4BIT_BP) {
  3165			nor->flags |= SNOR_F_HAS_4BIT_BP;
  3166			if (info->flags & SPI_NOR_BP3_SR_BIT6)
  3167				nor->flags |= SNOR_F_HAS_SR_BP3_BIT6;
  3168		}
  3169	
  3170		if (info->flags & SPI_NOR_NO_ERASE)
  3171			mtd->flags |= MTD_NO_ERASE;
  3172	
  3173		mtd->dev.parent = dev;
  3174		nor->page_size = nor->params->page_size;
  3175		mtd->writebufsize = nor->page_size;
  3176	
  3177		if (of_property_read_bool(np, "broken-flash-reset"))
  3178			nor->flags |= SNOR_F_BROKEN_RESET;
  3179	
  3180		/*
  3181		 * Configure the SPI memory:
  3182		 * - select op codes for (Fast) Read, Page Program and Sector Erase.
  3183		 * - set the number of dummy cycles (mode cycles + wait states).
  3184		 * - set the SPI protocols for register and memory accesses.
  3185		 */
  3186		ret = spi_nor_setup(nor, hwcaps);
  3187		if (ret)
  3188			return ret;
  3189	
  3190		if (info->flags & SPI_NOR_4B_OPCODES)
  3191			nor->flags |= SNOR_F_4B_OPCODES;
  3192	
  3193		if (info->flags & SPI_NOR_IO_MODE_EN_VOLATILE)
  3194			nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE;
  3195	
  3196		ret = spi_nor_set_addr_width(nor);
  3197		if (ret)
  3198			return ret;
  3199	
  3200		spi_nor_register_locking_ops(nor);
  3201	
> 3202		spi_nor_register_security_ops(nor);
  3203	
  3204		/* Send all the required SPI flash commands to initialize device */
  3205		ret = spi_nor_init(nor);
  3206		if (ret)
  3207			return ret;
  3208	
  3209		/* Configure OTP parameters and ops */
  3210		spi_nor_otp_init(nor);
  3211	
  3212		dev_info(dev, "%s (%lld Kbytes)\n", info->name,
  3213				(long long)mtd->size >> 10);
  3214	
  3215		dev_dbg(dev,
  3216			"mtd .name = %s, .size = 0x%llx (%lldMiB), "
  3217			".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
  3218			mtd->name, (long long)mtd->size, (long long)(mtd->size >> 20),
  3219			mtd->erasesize, mtd->erasesize / 1024, mtd->numeraseregions);
  3220	
  3221		if (mtd->numeraseregions)
  3222			for (i = 0; i < mtd->numeraseregions; i++)
  3223				dev_dbg(dev,
  3224					"mtd.eraseregions[%d] = { .offset = 0x%llx, "
  3225					".erasesize = 0x%.8x (%uKiB), "
  3226					".numblocks = %d }\n",
  3227					i, (long long)mtd->eraseregions[i].offset,
  3228					mtd->eraseregions[i].erasesize,
  3229					mtd->eraseregions[i].erasesize / 1024,
  3230					mtd->eraseregions[i].numblocks);
  3231		return 0;
  3232	}
  3233	EXPORT_SYMBOL_GPL(spi_nor_scan);
  3234	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
kernel test robot Oct. 28, 2021, 4:43 a.m. UTC | #3
Hi,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on mtd/mtd/next]
[also build test ERROR on mtd/mtd/fixes v5.15-rc7 next-20211027]
[cannot apply to mtd/spi-nor/next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/shiva-linuxworks-gmail-com/enabling-Advanced-protection-and-security-features/20211027-183458
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next
config: i386-buildonly-randconfig-r005-20211027 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 5db7568a6a1fcb408eb8988abdaff2a225a8eb72)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/d26eac1611c4409954b4d0c44215e1a53aa7605a
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review shiva-linuxworks-gmail-com/enabling-Advanced-protection-and-security-features/20211027-183458
        git checkout d26eac1611c4409954b4d0c44215e1a53aa7605a
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> drivers/mtd/spi-nor/core.c:3202:2: error: implicit declaration of function 'spi_nor_register_security_ops' [-Werror,-Wimplicit-function-declaration]
           spi_nor_register_security_ops(nor);
           ^
   drivers/mtd/spi-nor/core.c:3202:2: note: did you mean 'spi_nor_register_locking_ops'?
   drivers/mtd/spi-nor/core.h:572:6: note: 'spi_nor_register_locking_ops' declared here
   void spi_nor_register_locking_ops(struct spi_nor *nor);
        ^
   1 error generated.
--
>> drivers/mtd/spi-nor/advprotsec.c:192:6: error: no previous prototype for function 'spi_nor_register_security_ops' [-Werror,-Wmissing-prototypes]
   void spi_nor_register_security_ops(struct spi_nor *nor)
        ^
   drivers/mtd/spi-nor/advprotsec.c:192:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   void spi_nor_register_security_ops(struct spi_nor *nor)
   ^
   static 
   1 error generated.


vim +/spi_nor_register_security_ops +3202 drivers/mtd/spi-nor/core.c

  3073	
  3074	int spi_nor_scan(struct spi_nor *nor, const char *name,
  3075			 const struct spi_nor_hwcaps *hwcaps)
  3076	{
  3077		const struct flash_info *info;
  3078		struct device *dev = nor->dev;
  3079		struct mtd_info *mtd = &nor->mtd;
  3080		struct device_node *np = spi_nor_get_flash_node(nor);
  3081		int ret;
  3082		int i;
  3083	
  3084		ret = spi_nor_check(nor);
  3085		if (ret)
  3086			return ret;
  3087	
  3088		/* Reset SPI protocol for all commands. */
  3089		nor->reg_proto = SNOR_PROTO_1_1_1;
  3090		nor->read_proto = SNOR_PROTO_1_1_1;
  3091		nor->write_proto = SNOR_PROTO_1_1_1;
  3092	
  3093		/*
  3094		 * We need the bounce buffer early to read/write registers when going
  3095		 * through the spi-mem layer (buffers have to be DMA-able).
  3096		 * For spi-mem drivers, we'll reallocate a new buffer if
  3097		 * nor->page_size turns out to be greater than PAGE_SIZE (which
  3098		 * shouldn't happen before long since NOR pages are usually less
  3099		 * than 1KB) after spi_nor_scan() returns.
  3100		 */
  3101		nor->bouncebuf_size = PAGE_SIZE;
  3102		nor->bouncebuf = devm_kmalloc(dev, nor->bouncebuf_size,
  3103					      GFP_KERNEL);
  3104		if (!nor->bouncebuf)
  3105			return -ENOMEM;
  3106	
  3107		info = spi_nor_get_flash_info(nor, name);
  3108		if (IS_ERR(info))
  3109			return PTR_ERR(info);
  3110	
  3111		nor->info = info;
  3112	
  3113		spi_nor_debugfs_init(nor, info);
  3114	
  3115		mutex_init(&nor->lock);
  3116	
  3117		/*
  3118		 * Make sure the XSR_RDY flag is set before calling
  3119		 * spi_nor_wait_till_ready(). Xilinx S3AN share MFR
  3120		 * with Atmel SPI NOR.
  3121		 */
  3122		if (info->flags & SPI_NOR_XSR_RDY)
  3123			nor->flags |=  SNOR_F_READY_XSR_RDY;
  3124	
  3125		if (info->flags & SPI_NOR_HAS_LOCK)
  3126			nor->flags |= SNOR_F_HAS_LOCK;
  3127	
  3128		mtd->_write = spi_nor_write;
  3129	
  3130		/* Init flash parameters based on flash_info struct and SFDP */
  3131		ret = spi_nor_init_params(nor);
  3132		if (ret)
  3133			return ret;
  3134	
  3135		if (!mtd->name)
  3136			mtd->name = dev_name(dev);
  3137		mtd->priv = nor;
  3138		mtd->type = MTD_NORFLASH;
  3139		mtd->writesize = nor->params->writesize;
  3140		mtd->flags = MTD_CAP_NORFLASH;
  3141		mtd->size = nor->params->size;
  3142		mtd->_erase = spi_nor_erase;
  3143		mtd->_read = spi_nor_read;
  3144		mtd->_suspend = spi_nor_suspend;
  3145		mtd->_resume = spi_nor_resume;
  3146		mtd->_get_device = spi_nor_get_device;
  3147		mtd->_put_device = spi_nor_put_device;
  3148	
  3149		if (info->flags & USE_FSR)
  3150			nor->flags |= SNOR_F_USE_FSR;
  3151		if (info->flags & SPI_NOR_HAS_TB) {
  3152			nor->flags |= SNOR_F_HAS_SR_TB;
  3153			if (info->flags & SPI_NOR_TB_SR_BIT6)
  3154				nor->flags |= SNOR_F_HAS_SR_TB_BIT6;
  3155		}
  3156	
  3157		if (info->flags & NO_CHIP_ERASE)
  3158			nor->flags |= SNOR_F_NO_OP_CHIP_ERASE;
  3159		if (info->flags & USE_CLSR)
  3160			nor->flags |= SNOR_F_USE_CLSR;
  3161		if (info->flags & SPI_NOR_SWP_IS_VOLATILE)
  3162			nor->flags |= SNOR_F_SWP_IS_VOLATILE;
  3163	
  3164		if (info->flags & SPI_NOR_4BIT_BP) {
  3165			nor->flags |= SNOR_F_HAS_4BIT_BP;
  3166			if (info->flags & SPI_NOR_BP3_SR_BIT6)
  3167				nor->flags |= SNOR_F_HAS_SR_BP3_BIT6;
  3168		}
  3169	
  3170		if (info->flags & SPI_NOR_NO_ERASE)
  3171			mtd->flags |= MTD_NO_ERASE;
  3172	
  3173		mtd->dev.parent = dev;
  3174		nor->page_size = nor->params->page_size;
  3175		mtd->writebufsize = nor->page_size;
  3176	
  3177		if (of_property_read_bool(np, "broken-flash-reset"))
  3178			nor->flags |= SNOR_F_BROKEN_RESET;
  3179	
  3180		/*
  3181		 * Configure the SPI memory:
  3182		 * - select op codes for (Fast) Read, Page Program and Sector Erase.
  3183		 * - set the number of dummy cycles (mode cycles + wait states).
  3184		 * - set the SPI protocols for register and memory accesses.
  3185		 */
  3186		ret = spi_nor_setup(nor, hwcaps);
  3187		if (ret)
  3188			return ret;
  3189	
  3190		if (info->flags & SPI_NOR_4B_OPCODES)
  3191			nor->flags |= SNOR_F_4B_OPCODES;
  3192	
  3193		if (info->flags & SPI_NOR_IO_MODE_EN_VOLATILE)
  3194			nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE;
  3195	
  3196		ret = spi_nor_set_addr_width(nor);
  3197		if (ret)
  3198			return ret;
  3199	
  3200		spi_nor_register_locking_ops(nor);
  3201	
> 3202		spi_nor_register_security_ops(nor);
  3203	
  3204		/* Send all the required SPI flash commands to initialize device */
  3205		ret = spi_nor_init(nor);
  3206		if (ret)
  3207			return ret;
  3208	
  3209		/* Configure OTP parameters and ops */
  3210		spi_nor_otp_init(nor);
  3211	
  3212		dev_info(dev, "%s (%lld Kbytes)\n", info->name,
  3213				(long long)mtd->size >> 10);
  3214	
  3215		dev_dbg(dev,
  3216			"mtd .name = %s, .size = 0x%llx (%lldMiB), "
  3217			".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
  3218			mtd->name, (long long)mtd->size, (long long)(mtd->size >> 20),
  3219			mtd->erasesize, mtd->erasesize / 1024, mtd->numeraseregions);
  3220	
  3221		if (mtd->numeraseregions)
  3222			for (i = 0; i < mtd->numeraseregions; i++)
  3223				dev_dbg(dev,
  3224					"mtd.eraseregions[%d] = { .offset = 0x%llx, "
  3225					".erasesize = 0x%.8x (%uKiB), "
  3226					".numblocks = %d }\n",
  3227					i, (long long)mtd->eraseregions[i].offset,
  3228					mtd->eraseregions[i].erasesize,
  3229					mtd->eraseregions[i].erasesize / 1024,
  3230					mtd->eraseregions[i].numblocks);
  3231		return 0;
  3232	}
  3233	EXPORT_SYMBOL_GPL(spi_nor_scan);
  3234	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Paul Barker Dec. 6, 2021, 11:03 a.m. UTC | #4
On 27/10/2021 11:33, shiva.linuxworks@gmail.com wrote:
> From: Shivamurthy Shastri <sshivamurthy@micron.com>
> 
> Added functionalities to support advanced securtiy and protection
> features in new SPI NOR flashes.
> 
> Signed-off-by: Shivamurthy Shastri <sshivamurthy@micron.com>
> ---
>   drivers/mtd/spi-nor/Makefile     |   2 +-
>   drivers/mtd/spi-nor/advprotsec.c | 209 +++++++++++++++++++++++++++++++
>   drivers/mtd/spi-nor/core.c       |   2 +
>   include/linux/mtd/mtd.h          |  19 +++
>   4 files changed, 231 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/mtd/spi-nor/advprotsec.c

The changes to drivers/mtd/spi-nor/core.h in patch 1 of this series can 
be merged into this patch, with the series re-ordered so this patch is 
first.

> 
> diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
> index 6b904e439372..8e96e2c65c7a 100644
> --- a/drivers/mtd/spi-nor/Makefile
> +++ b/drivers/mtd/spi-nor/Makefile
> @@ -1,6 +1,6 @@
>   # SPDX-License-Identifier: GPL-2.0
>   
> -spi-nor-objs			:= core.o sfdp.o swp.o otp.o sysfs.o
> +spi-nor-objs			:= core.o sfdp.o swp.o otp.o advprotsec.o sysfs.o
>   spi-nor-objs			+= atmel.o
>   spi-nor-objs			+= catalyst.o
>   spi-nor-objs			+= eon.o
> diff --git a/drivers/mtd/spi-nor/advprotsec.c b/drivers/mtd/spi-nor/advprotsec.c
> new file mode 100644
> index 000000000000..4dc8e67b16ef
> --- /dev/null
> +++ b/drivers/mtd/spi-nor/advprotsec.c
> @@ -0,0 +1,209 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * SPI NOR Advanced Sector Protection and Security Features
> + *
> + * Copyright (C) 2021 Micron Technology, Inc.
> + */
> +
> +#include <linux/mtd/mtd.h>
> +#include <linux/mtd/spi-nor.h>
> +
> +#include "core.h"
> +
> +static int spi_nor_secure_read(struct mtd_info *mtd, size_t len, u8 *buf)
> +{
> +	struct spi_nor *nor = mtd_to_spi_nor(mtd);
> +	int ret;
> +
> +	ret = spi_nor_lock_and_prep(nor);
> +	if (ret)
> +		return ret;
> +
> +	ret = nor->params->sec_ops->secure_read(nor, len, buf);
> +
> +	spi_nor_unlock_and_unprep(nor);
> +	return ret;
> +}
> +
> +static int spi_nor_secure_write(struct mtd_info *mtd, size_t len, u8 *buf)
> +{
> +	struct spi_nor *nor = mtd_to_spi_nor(mtd);
> +	int ret;
> +
> +	ret = spi_nor_lock_and_prep(nor);
> +	if (ret)
> +		return ret;
> +
> +	ret = nor->params->sec_ops->secure_write(nor, len, buf);
> +
> +	spi_nor_unlock_and_unprep(nor);
> +	return ret;
> +}
> +
> +static int spi_nor_read_vlock_bits(struct mtd_info *mtd, u32 addr, size_t len,
> +				   u8 *buf)
> +{
> +	struct spi_nor *nor = mtd_to_spi_nor(mtd);
> +	int ret;
> +
> +	ret = spi_nor_lock_and_prep(nor);
> +	if (ret)
> +		return ret;
> +
> +	ret = nor->params->sec_ops->read_vlock_bits(nor, addr, len, buf);
> +
> +	spi_nor_unlock_and_unprep(nor);
> +	return ret;
> +}
> +
> +static int spi_nor_write_vlock_bits(struct mtd_info *mtd, u32 addr, size_t len,
> +				    u8 *buf)
> +{
> +	struct spi_nor *nor = mtd_to_spi_nor(mtd);
> +	int ret;
> +
> +	ret = spi_nor_lock_and_prep(nor);
> +	if (ret)
> +		return ret;
> +
> +	ret = spi_nor_write_enable(nor);
> +	if (ret)
> +		return ret;
> +
> +	ret = nor->params->sec_ops->write_vlock_bits(nor, addr, len, buf);
> +	if (ret)
> +		return ret;
> +
> +	ret = spi_nor_write_disable(nor);
> +
> +	spi_nor_unlock_and_unprep(nor);
> +	return ret;
> +}
> +
> +static int spi_nor_read_nvlock_bits(struct mtd_info *mtd, u32 addr, size_t len,
> +				    u8 *buf)
> +{
> +	struct spi_nor *nor = mtd_to_spi_nor(mtd);
> +	int ret;
> +
> +	ret = spi_nor_lock_and_prep(nor);
> +	if (ret)
> +		return ret;
> +
> +	ret = nor->params->sec_ops->read_nvlock_bits(nor, addr, len, buf);
> +
> +	spi_nor_unlock_and_unprep(nor);
> +	return ret;
> +}
> +
> +static int spi_nor_write_nvlock_bits(struct mtd_info *mtd, u32 addr)
> +{
> +	struct spi_nor *nor = mtd_to_spi_nor(mtd);
> +	int ret;
> +
> +	ret = spi_nor_lock_and_prep(nor);
> +	if (ret)
> +		return ret;
> +
> +	ret = spi_nor_write_enable(nor);
> +	if (ret)
> +		return ret;
> +
> +	ret = nor->params->sec_ops->write_nvlock_bits(nor, addr);
> +	if (ret)
> +		return ret;
> +
> +	ret = spi_nor_write_disable(nor);
> +
> +	spi_nor_unlock_and_unprep(nor);
> +	return ret;
> +}
> +
> +static int spi_nor_erase_nvlock_bits(struct mtd_info *mtd)
> +{
> +	struct spi_nor *nor = mtd_to_spi_nor(mtd);
> +	int ret;
> +
> +	ret = spi_nor_lock_and_prep(nor);
> +	if (ret)
> +		return ret;
> +
> +	ret = spi_nor_write_enable(nor);
> +	if (ret)
> +		return ret;
> +
> +	ret = nor->params->sec_ops->erase_nvlock_bits(nor);
> +	if (ret)
> +		return ret;
> +
> +	ret = spi_nor_write_disable(nor);
> +
> +	spi_nor_unlock_and_unprep(nor);
> +	return ret;
> +}
> +
> +static int spi_nor_read_global_freeze_bits(struct mtd_info *mtd, size_t len,
> +					   u8 *buf)
> +{
> +	struct spi_nor *nor = mtd_to_spi_nor(mtd);
> +	int ret;
> +
> +	ret = spi_nor_lock_and_prep(nor);
> +	if (ret)
> +		return ret;
> +
> +	ret = nor->params->sec_ops->read_global_freeze_bits(nor, len, buf);
> +
> +	spi_nor_unlock_and_unprep(nor);
> +	return ret;
> +}
> +
> +static int spi_nor_write_global_freeze_bits(struct mtd_info *mtd, size_t len,
> +					    u8 *buf)
> +{
> +	struct spi_nor *nor = mtd_to_spi_nor(mtd);
> +	int ret;
> +
> +	ret = spi_nor_lock_and_prep(nor);
> +	if (ret)
> +		return ret;
> +
> +	ret = nor->params->sec_ops->write_global_freeze_bits(nor, len, buf);
> +
> +	spi_nor_unlock_and_unprep(nor);
> +	return ret;
> +}
> +
> +static int spi_nor_read_password(struct mtd_info *mtd, size_t len, u8 *buf)
> +{
> +	struct spi_nor *nor = mtd_to_spi_nor(mtd);
> +	int ret;
> +
> +	ret = spi_nor_lock_and_prep(nor);
> +	if (ret)
> +		return ret;
> +
> +	ret = nor->params->sec_ops->read_password(nor, len, buf);
> +
> +	spi_nor_unlock_and_unprep(nor);
> +	return ret;
> +}
> +
> +void spi_nor_register_security_ops(struct spi_nor *nor)
> +{
> +	struct mtd_info *mtd = &nor->mtd;
> +
> +	if (!nor->params->sec_ops)
> +		return;
> +
> +	mtd->_secure_packet_read = spi_nor_secure_read;
> +	mtd->_secure_packet_write = spi_nor_secure_write;
> +	mtd->_read_vlock_bits = spi_nor_read_vlock_bits;
> +	mtd->_write_vlock_bits = spi_nor_write_vlock_bits;
> +	mtd->_read_nvlock_bits = spi_nor_read_nvlock_bits;
> +	mtd->_write_nvlock_bits = spi_nor_write_nvlock_bits;
> +	mtd->_erase_nvlock_bits = spi_nor_erase_nvlock_bits;
> +	mtd->_read_global_freeze_bits = spi_nor_read_global_freeze_bits;
> +	mtd->_write_global_freeze_bits = spi_nor_write_global_freeze_bits;
> +	mtd->_read_password = spi_nor_read_password;

This approach requires all or none of the sec_ops functions to be 
implemented. It doesn't consider other drivers which may be able to 
implement a subset of the sec_ops functions.

I also think it would be better not to use extra function pointers here 
and just let other code call the functions defined above directly. The 
caller of these functions will need to check that the pointers aren't 
NULL before calling them anyway, so I think we may as well call the 
functions directly and have each of them check that the corresponding 
sec_ops field is non-NULL before calling it.

> +}
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index cc08bd707378..864f3c7783b3 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -3199,6 +3199,8 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
>   
>   	spi_nor_register_locking_ops(nor);
>   
> +	spi_nor_register_security_ops(nor);
> +
>   	/* Send all the required SPI flash commands to initialize device */
>   	ret = spi_nor_init(nor);
>   	if (ret)
> diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
> index 88227044fc86..bce358c9fb94 100644
> --- a/include/linux/mtd/mtd.h
> +++ b/include/linux/mtd/mtd.h
> @@ -360,6 +360,25 @@ struct mtd_info {
>   	int (*_get_device) (struct mtd_info *mtd);
>   	void (*_put_device) (struct mtd_info *mtd);
>   
> +	/*
> +	 * Security Operations
> +	 */
> +	int (*_secure_packet_read)(struct mtd_info *mtd, size_t len, u8 *buf);
> +	int (*_secure_packet_write)(struct mtd_info *mtd, size_t len, u8 *buf);
> +	int (*_read_vlock_bits)(struct mtd_info *mtd, u32 addr, size_t len,
> +				u8 *buf);
> +	int (*_write_vlock_bits)(struct mtd_info *mtd, u32 addr, size_t len,
> +				 u8 *buf);
> +	int (*_read_nvlock_bits)(struct mtd_info *mtd, u32 addr, size_t len,
> +				 u8 *buf);
> +	int (*_write_nvlock_bits)(struct mtd_info *mtd, u32 addr);
> +	int (*_erase_nvlock_bits)(struct mtd_info *mtd);
> +	int (*_read_global_freeze_bits)(struct mtd_info *mtd, size_t len,
> +					u8 *buf);
> +	int (*_write_global_freeze_bits)(struct mtd_info *mtd, size_t len,
> +					 u8 *buf);
> +	int (*_read_password)(struct mtd_info *mtd, size_t len, u8 *buf);
> +
>   	/*
>   	 * flag indicates a panic write, low level drivers can take appropriate
>   	 * action if required to ensure writes go through
> 

Thanks,
diff mbox series

Patch

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 6b904e439372..8e96e2c65c7a 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -1,6 +1,6 @@ 
 # SPDX-License-Identifier: GPL-2.0
 
-spi-nor-objs			:= core.o sfdp.o swp.o otp.o sysfs.o
+spi-nor-objs			:= core.o sfdp.o swp.o otp.o advprotsec.o sysfs.o
 spi-nor-objs			+= atmel.o
 spi-nor-objs			+= catalyst.o
 spi-nor-objs			+= eon.o
diff --git a/drivers/mtd/spi-nor/advprotsec.c b/drivers/mtd/spi-nor/advprotsec.c
new file mode 100644
index 000000000000..4dc8e67b16ef
--- /dev/null
+++ b/drivers/mtd/spi-nor/advprotsec.c
@@ -0,0 +1,209 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SPI NOR Advanced Sector Protection and Security Features
+ *
+ * Copyright (C) 2021 Micron Technology, Inc.
+ */
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static int spi_nor_secure_read(struct mtd_info *mtd, size_t len, u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->secure_read(nor, len, buf);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_secure_write(struct mtd_info *mtd, size_t len, u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->secure_write(nor, len, buf);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_read_vlock_bits(struct mtd_info *mtd, u32 addr, size_t len,
+				   u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->read_vlock_bits(nor, addr, len, buf);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_write_vlock_bits(struct mtd_info *mtd, u32 addr, size_t len,
+				    u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = spi_nor_write_enable(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->write_vlock_bits(nor, addr, len, buf);
+	if (ret)
+		return ret;
+
+	ret = spi_nor_write_disable(nor);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_read_nvlock_bits(struct mtd_info *mtd, u32 addr, size_t len,
+				    u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->read_nvlock_bits(nor, addr, len, buf);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_write_nvlock_bits(struct mtd_info *mtd, u32 addr)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = spi_nor_write_enable(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->write_nvlock_bits(nor, addr);
+	if (ret)
+		return ret;
+
+	ret = spi_nor_write_disable(nor);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_erase_nvlock_bits(struct mtd_info *mtd)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = spi_nor_write_enable(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->erase_nvlock_bits(nor);
+	if (ret)
+		return ret;
+
+	ret = spi_nor_write_disable(nor);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_read_global_freeze_bits(struct mtd_info *mtd, size_t len,
+					   u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->read_global_freeze_bits(nor, len, buf);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_write_global_freeze_bits(struct mtd_info *mtd, size_t len,
+					    u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->write_global_freeze_bits(nor, len, buf);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_read_password(struct mtd_info *mtd, size_t len, u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->read_password(nor, len, buf);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+void spi_nor_register_security_ops(struct spi_nor *nor)
+{
+	struct mtd_info *mtd = &nor->mtd;
+
+	if (!nor->params->sec_ops)
+		return;
+
+	mtd->_secure_packet_read = spi_nor_secure_read;
+	mtd->_secure_packet_write = spi_nor_secure_write;
+	mtd->_read_vlock_bits = spi_nor_read_vlock_bits;
+	mtd->_write_vlock_bits = spi_nor_write_vlock_bits;
+	mtd->_read_nvlock_bits = spi_nor_read_nvlock_bits;
+	mtd->_write_nvlock_bits = spi_nor_write_nvlock_bits;
+	mtd->_erase_nvlock_bits = spi_nor_erase_nvlock_bits;
+	mtd->_read_global_freeze_bits = spi_nor_read_global_freeze_bits;
+	mtd->_write_global_freeze_bits = spi_nor_write_global_freeze_bits;
+	mtd->_read_password = spi_nor_read_password;
+}
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index cc08bd707378..864f3c7783b3 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -3199,6 +3199,8 @@  int spi_nor_scan(struct spi_nor *nor, const char *name,
 
 	spi_nor_register_locking_ops(nor);
 
+	spi_nor_register_security_ops(nor);
+
 	/* Send all the required SPI flash commands to initialize device */
 	ret = spi_nor_init(nor);
 	if (ret)
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 88227044fc86..bce358c9fb94 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -360,6 +360,25 @@  struct mtd_info {
 	int (*_get_device) (struct mtd_info *mtd);
 	void (*_put_device) (struct mtd_info *mtd);
 
+	/*
+	 * Security Operations
+	 */
+	int (*_secure_packet_read)(struct mtd_info *mtd, size_t len, u8 *buf);
+	int (*_secure_packet_write)(struct mtd_info *mtd, size_t len, u8 *buf);
+	int (*_read_vlock_bits)(struct mtd_info *mtd, u32 addr, size_t len,
+				u8 *buf);
+	int (*_write_vlock_bits)(struct mtd_info *mtd, u32 addr, size_t len,
+				 u8 *buf);
+	int (*_read_nvlock_bits)(struct mtd_info *mtd, u32 addr, size_t len,
+				 u8 *buf);
+	int (*_write_nvlock_bits)(struct mtd_info *mtd, u32 addr);
+	int (*_erase_nvlock_bits)(struct mtd_info *mtd);
+	int (*_read_global_freeze_bits)(struct mtd_info *mtd, size_t len,
+					u8 *buf);
+	int (*_write_global_freeze_bits)(struct mtd_info *mtd, size_t len,
+					 u8 *buf);
+	int (*_read_password)(struct mtd_info *mtd, size_t len, u8 *buf);
+
 	/*
 	 * flag indicates a panic write, low level drivers can take appropriate
 	 * action if required to ensure writes go through