Skip to content

Commit 13b8976

Browse files
Mani-Sadhasivammiquelraynal
authored andcommitted
mtd: rawnand: Add support for secure regions in NAND memory
On a typical end product, a vendor may choose to secure some regions in the NAND memory which are supposed to stay intact between FW upgrades. The access to those regions will be blocked by a secure element like Trustzone. So the normal world software like Linux kernel should not touch these regions (including reading). The regions are declared using a NAND chip DT property, "secure-regions". So let's make use of this property in the raw NAND core and skip access to the secure regions present in a system. Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Link: https://lore.kernel.org/linux-mtd/20210402150128.29128-4-manivannan.sadhasivam@linaro.org
1 parent ee59010 commit 13b8976

2 files changed

Lines changed: 113 additions & 1 deletion

File tree

drivers/mtd/nand/raw/nand_base.c

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,11 +278,48 @@ static int nand_block_bad(struct nand_chip *chip, loff_t ofs)
278278
return 0;
279279
}
280280

281+
/**
282+
* nand_region_is_secured() - Check if the region is secured
283+
* @chip: NAND chip object
284+
* @offset: Offset of the region to check
285+
* @size: Size of the region to check
286+
*
287+
* Checks if the region is secured by comparing the offset and size with the
288+
* list of secure regions obtained from DT. Returns true if the region is
289+
* secured else false.
290+
*/
291+
static bool nand_region_is_secured(struct nand_chip *chip, loff_t offset, u64 size)
292+
{
293+
int i;
294+
295+
/* Skip touching the secure regions if present */
296+
for (i = 0; i < chip->nr_secure_regions; i++) {
297+
const struct nand_secure_region *region = &chip->secure_regions[i];
298+
299+
if (offset + size <= region->offset ||
300+
offset >= region->offset + region->size)
301+
continue;
302+
303+
pr_debug("%s: Region 0x%llx - 0x%llx is secured!",
304+
__func__, offset, offset + size);
305+
306+
return true;
307+
}
308+
309+
return false;
310+
}
311+
281312
static int nand_isbad_bbm(struct nand_chip *chip, loff_t ofs)
282313
{
314+
struct mtd_info *mtd = nand_to_mtd(chip);
315+
283316
if (chip->options & NAND_NO_BBM_QUIRK)
284317
return 0;
285318

319+
/* Check if the region is secured */
320+
if (nand_region_is_secured(chip, ofs, mtd->erasesize))
321+
return -EIO;
322+
286323
if (chip->legacy.block_bad)
287324
return chip->legacy.block_bad(chip, ofs);
288325

@@ -397,6 +434,10 @@ static int nand_do_write_oob(struct nand_chip *chip, loff_t to,
397434
return -EINVAL;
398435
}
399436

437+
/* Check if the region is secured */
438+
if (nand_region_is_secured(chip, to, ops->ooblen))
439+
return -EIO;
440+
400441
chipnr = (int)(to >> chip->chip_shift);
401442

402443
/*
@@ -3128,6 +3169,10 @@ static int nand_do_read_ops(struct nand_chip *chip, loff_t from,
31283169
int retry_mode = 0;
31293170
bool ecc_fail = false;
31303171

3172+
/* Check if the region is secured */
3173+
if (nand_region_is_secured(chip, from, readlen))
3174+
return -EIO;
3175+
31313176
chipnr = (int)(from >> chip->chip_shift);
31323177
nand_select_target(chip, chipnr);
31333178

@@ -3459,6 +3504,10 @@ static int nand_do_read_oob(struct nand_chip *chip, loff_t from,
34593504
pr_debug("%s: from = 0x%08Lx, len = %i\n",
34603505
__func__, (unsigned long long)from, readlen);
34613506

3507+
/* Check if the region is secured */
3508+
if (nand_region_is_secured(chip, from, readlen))
3509+
return -EIO;
3510+
34623511
stats = mtd->ecc_stats;
34633512

34643513
len = mtd_oobavail(mtd, ops);
@@ -3980,6 +4029,10 @@ static int nand_do_write_ops(struct nand_chip *chip, loff_t to,
39804029
return -EINVAL;
39814030
}
39824031

4032+
/* Check if the region is secured */
4033+
if (nand_region_is_secured(chip, to, writelen))
4034+
return -EIO;
4035+
39834036
column = to & (mtd->writesize - 1);
39844037

39854038
chipnr = (int)(to >> chip->chip_shift);
@@ -4181,6 +4234,10 @@ int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr,
41814234
if (check_offs_len(chip, instr->addr, instr->len))
41824235
return -EINVAL;
41834236

4237+
/* Check if the region is secured */
4238+
if (nand_region_is_secured(chip, instr->addr, instr->len))
4239+
return -EIO;
4240+
41844241
/* Grab the lock and see if the device is available */
41854242
ret = nand_get_device(chip);
41864243
if (ret)
@@ -4996,6 +5053,31 @@ static bool of_get_nand_on_flash_bbt(struct device_node *np)
49965053
return of_property_read_bool(np, "nand-on-flash-bbt");
49975054
}
49985055

5056+
static int of_get_nand_secure_regions(struct nand_chip *chip)
5057+
{
5058+
struct device_node *dn = nand_get_flash_node(chip);
5059+
int nr_elem, i, j;
5060+
5061+
nr_elem = of_property_count_elems_of_size(dn, "secure-regions", sizeof(u64));
5062+
if (!nr_elem)
5063+
return 0;
5064+
5065+
chip->nr_secure_regions = nr_elem / 2;
5066+
chip->secure_regions = kcalloc(chip->nr_secure_regions, sizeof(*chip->secure_regions),
5067+
GFP_KERNEL);
5068+
if (!chip->secure_regions)
5069+
return -ENOMEM;
5070+
5071+
for (i = 0, j = 0; i < chip->nr_secure_regions; i++, j += 2) {
5072+
of_property_read_u64_index(dn, "secure-regions", j,
5073+
&chip->secure_regions[i].offset);
5074+
of_property_read_u64_index(dn, "secure-regions", j + 1,
5075+
&chip->secure_regions[i].size);
5076+
}
5077+
5078+
return 0;
5079+
}
5080+
49995081
static int rawnand_dt_init(struct nand_chip *chip)
50005082
{
50015083
struct nand_device *nand = mtd_to_nanddev(nand_to_mtd(chip));
@@ -5952,17 +6034,30 @@ static int nand_scan_tail(struct nand_chip *chip)
59526034
goto err_free_interface_config;
59536035
}
59546036

6037+
/*
6038+
* Look for secure regions in the NAND chip. These regions are supposed
6039+
* to be protected by a secure element like Trustzone. So the read/write
6040+
* accesses to these regions will be blocked in the runtime by this
6041+
* driver.
6042+
*/
6043+
ret = of_get_nand_secure_regions(chip);
6044+
if (ret)
6045+
goto err_free_interface_config;
6046+
59556047
/* Check, if we should skip the bad block table scan */
59566048
if (chip->options & NAND_SKIP_BBTSCAN)
59576049
return 0;
59586050

59596051
/* Build bad block table */
59606052
ret = nand_create_bbt(chip);
59616053
if (ret)
5962-
goto err_free_interface_config;
6054+
goto err_free_secure_regions;
59636055

59646056
return 0;
59656057

6058+
err_free_secure_regions:
6059+
kfree(chip->secure_regions);
6060+
59666061
err_free_interface_config:
59676062
kfree(chip->best_interface_config);
59686063

@@ -6050,6 +6145,9 @@ void nand_cleanup(struct nand_chip *chip)
60506145

60516146
nanddev_cleanup(&chip->base);
60526147

6148+
/* Free secure regions data */
6149+
kfree(chip->secure_regions);
6150+
60536151
/* Free bad block table memory */
60546152
kfree(chip->bbt);
60556153
kfree(chip->data_buf);

include/linux/mtd/rawnand.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,16 @@ struct nand_manufacturer {
10351035
void *priv;
10361036
};
10371037

1038+
/**
1039+
* struct nand_secure_region - NAND secure region structure
1040+
* @offset: Offset of the start of the secure region
1041+
* @size: Size of the secure region
1042+
*/
1043+
struct nand_secure_region {
1044+
u64 offset;
1045+
u64 size;
1046+
};
1047+
10381048
/**
10391049
* struct nand_chip - NAND Private Flash Chip Data
10401050
* @base: Inherit from the generic NAND device
@@ -1085,6 +1095,8 @@ struct nand_manufacturer {
10851095
* NAND Controller drivers should not modify this value, but they're
10861096
* allowed to read it.
10871097
* @read_retries: The number of read retry modes supported
1098+
* @secure_regions: Structure containing the secure regions info
1099+
* @nr_secure_regions: Number of secure regions
10881100
* @controller: The hardware controller structure which is shared among multiple
10891101
* independent devices
10901102
* @ecc: The ECC controller structure
@@ -1134,6 +1146,8 @@ struct nand_chip {
11341146
unsigned int suspended : 1;
11351147
int cur_cs;
11361148
int read_retries;
1149+
struct nand_secure_region *secure_regions;
1150+
u8 nr_secure_regions;
11371151

11381152
/* Externals */
11391153
struct nand_controller *controller;

0 commit comments

Comments
 (0)