ecbcbc7b75
The pointer returned by kzalloc should be tested for NULL
to avoid potential NULL pointer dereference later. Incorrect
pointer was being tested for NULL. Bug introduced by commit fbcf62a3
(mtd: physmap_of: move parse_obsolete_partitions to become separate
parser).
This patch fixes this bug.
Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
Cc: stable@vger.kernel.org [3.2+]
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
184 lines
4 KiB
C
184 lines
4 KiB
C
/*
|
|
* Flash partitions described by the OF (or flattened) device tree
|
|
*
|
|
* Copyright © 2006 MontaVista Software Inc.
|
|
* Author: Vitaly Wool <vwool@ru.mvista.com>
|
|
*
|
|
* Revised to handle newer style flash binding by:
|
|
* Copyright © 2007 David Gibson, IBM Corporation.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2 of the License, or (at your
|
|
* option) any later version.
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/init.h>
|
|
#include <linux/of.h>
|
|
#include <linux/mtd/mtd.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/mtd/partitions.h>
|
|
|
|
static int parse_ofpart_partitions(struct mtd_info *master,
|
|
struct mtd_partition **pparts,
|
|
struct mtd_part_parser_data *data)
|
|
{
|
|
struct device_node *node;
|
|
const char *partname;
|
|
struct device_node *pp;
|
|
int nr_parts, i;
|
|
|
|
|
|
if (!data)
|
|
return 0;
|
|
|
|
node = data->of_node;
|
|
if (!node)
|
|
return 0;
|
|
|
|
/* First count the subnodes */
|
|
pp = NULL;
|
|
nr_parts = 0;
|
|
while ((pp = of_get_next_child(node, pp)))
|
|
nr_parts++;
|
|
|
|
if (nr_parts == 0)
|
|
return 0;
|
|
|
|
*pparts = kzalloc(nr_parts * sizeof(**pparts), GFP_KERNEL);
|
|
if (!*pparts)
|
|
return -ENOMEM;
|
|
|
|
pp = NULL;
|
|
i = 0;
|
|
while ((pp = of_get_next_child(node, pp))) {
|
|
const __be32 *reg;
|
|
int len;
|
|
|
|
reg = of_get_property(pp, "reg", &len);
|
|
if (!reg) {
|
|
nr_parts--;
|
|
continue;
|
|
}
|
|
|
|
(*pparts)[i].offset = be32_to_cpu(reg[0]);
|
|
(*pparts)[i].size = be32_to_cpu(reg[1]);
|
|
|
|
partname = of_get_property(pp, "label", &len);
|
|
if (!partname)
|
|
partname = of_get_property(pp, "name", &len);
|
|
(*pparts)[i].name = (char *)partname;
|
|
|
|
if (of_get_property(pp, "read-only", &len))
|
|
(*pparts)[i].mask_flags = MTD_WRITEABLE;
|
|
|
|
i++;
|
|
}
|
|
|
|
if (!i) {
|
|
of_node_put(pp);
|
|
pr_err("No valid partition found on %s\n", node->full_name);
|
|
kfree(*pparts);
|
|
*pparts = NULL;
|
|
return -EINVAL;
|
|
}
|
|
|
|
return nr_parts;
|
|
}
|
|
|
|
static struct mtd_part_parser ofpart_parser = {
|
|
.owner = THIS_MODULE,
|
|
.parse_fn = parse_ofpart_partitions,
|
|
.name = "ofpart",
|
|
};
|
|
|
|
static int parse_ofoldpart_partitions(struct mtd_info *master,
|
|
struct mtd_partition **pparts,
|
|
struct mtd_part_parser_data *data)
|
|
{
|
|
struct device_node *dp;
|
|
int i, plen, nr_parts;
|
|
const struct {
|
|
__be32 offset, len;
|
|
} *part;
|
|
const char *names;
|
|
|
|
if (!data)
|
|
return 0;
|
|
|
|
dp = data->of_node;
|
|
if (!dp)
|
|
return 0;
|
|
|
|
part = of_get_property(dp, "partitions", &plen);
|
|
if (!part)
|
|
return 0; /* No partitions found */
|
|
|
|
pr_warning("Device tree uses obsolete partition map binding: %s\n",
|
|
dp->full_name);
|
|
|
|
nr_parts = plen / sizeof(part[0]);
|
|
|
|
*pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL);
|
|
if (!*pparts)
|
|
return -ENOMEM;
|
|
|
|
names = of_get_property(dp, "partition-names", &plen);
|
|
|
|
for (i = 0; i < nr_parts; i++) {
|
|
(*pparts)[i].offset = be32_to_cpu(part->offset);
|
|
(*pparts)[i].size = be32_to_cpu(part->len) & ~1;
|
|
/* bit 0 set signifies read only partition */
|
|
if (be32_to_cpu(part->len) & 1)
|
|
(*pparts)[i].mask_flags = MTD_WRITEABLE;
|
|
|
|
if (names && (plen > 0)) {
|
|
int len = strlen(names) + 1;
|
|
|
|
(*pparts)[i].name = (char *)names;
|
|
plen -= len;
|
|
names += len;
|
|
} else {
|
|
(*pparts)[i].name = "unnamed";
|
|
}
|
|
|
|
part++;
|
|
}
|
|
|
|
return nr_parts;
|
|
}
|
|
|
|
static struct mtd_part_parser ofoldpart_parser = {
|
|
.owner = THIS_MODULE,
|
|
.parse_fn = parse_ofoldpart_partitions,
|
|
.name = "ofoldpart",
|
|
};
|
|
|
|
static int __init ofpart_parser_init(void)
|
|
{
|
|
int rc;
|
|
rc = register_mtd_parser(&ofpart_parser);
|
|
if (rc)
|
|
goto out;
|
|
|
|
rc = register_mtd_parser(&ofoldpart_parser);
|
|
if (!rc)
|
|
return 0;
|
|
|
|
deregister_mtd_parser(&ofoldpart_parser);
|
|
out:
|
|
return rc;
|
|
}
|
|
|
|
module_init(ofpart_parser_init);
|
|
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_DESCRIPTION("Parser for MTD partitioning information in device tree");
|
|
MODULE_AUTHOR("Vitaly Wool, David Gibson");
|
|
/*
|
|
* When MTD core cannot find the requested parser, it tries to load the module
|
|
* with the same name. Since we provide the ofoldpart parser, we should have
|
|
* the corresponding alias.
|
|
*/
|
|
MODULE_ALIAS("ofoldpart");
|