openwrt-owl/target/linux/lantiq/patches-4.4/0101-find_active_root.patch

94 lines
2.1 KiB
Diff

--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -25,6 +25,38 @@ static bool node_has_compatible(struct d
return of_get_property(pp, "compatible", NULL);
}
+static uint8_t * brnboot_get_selected_root_part(struct mtd_info *master,
+ loff_t offset)
+{
+ static uint8_t root_id;
+ int err, len;
+
+ err = mtd_read(master, offset, 0x01, &len, &root_id);
+
+ if (mtd_is_bitflip(err) || !err)
+ return &root_id;
+
+ return NULL;
+}
+
+static void brnboot_set_active_root_part(struct mtd_partition *pparts,
+ struct device_node **part_nodes,
+ int nr_parts,
+ uint8_t *root_id)
+{
+ int i;
+
+ for (i = 0; i < nr_parts; i++) {
+ int part_root_id;
+
+ if (!of_property_read_u32(part_nodes[i], "brnboot,root-id", &part_root_id)
+ && part_root_id == *root_id) {
+ pparts[i].name = "firmware";
+ break;
+ }
+ }
+}
+
static int parse_ofpart_partitions(struct mtd_info *master,
struct mtd_partition **pparts,
struct mtd_part_parser_data *data)
@@ -35,7 +67,8 @@ static int parse_ofpart_partitions(struc
struct device_node *pp;
int nr_parts, i, ret = 0;
bool dedicated = true;
-
+ uint8_t *proot_id = NULL;
+ struct device_node **part_nodes;
if (!data)
return 0;
@@ -73,7 +106,9 @@ static int parse_ofpart_partitions(struc
return 0;
*pparts = kzalloc(nr_parts * sizeof(**pparts), GFP_KERNEL);
- if (!*pparts)
+ part_nodes = kzalloc(nr_parts * sizeof(*part_nodes), GFP_KERNEL);
+
+ if (!*pparts || !part_nodes)
return -ENOMEM;
i = 0;
@@ -121,12 +156,22 @@ static int parse_ofpart_partitions(struc
if (of_get_property(pp, "lock", &len))
(*pparts)[i].mask_flags |= MTD_POWERUP_LOCK;
+ if (!proot_id && of_device_is_compatible(pp, "brnboot,root-selector"))
+ proot_id = brnboot_get_selected_root_part(master, (*pparts)[i].offset);
+
+ part_nodes[i] = pp;
+
i++;
}
if (!nr_parts)
goto ofpart_none;
+ if (proot_id)
+ brnboot_set_active_root_part(*pparts, part_nodes, nr_parts, proot_id);
+
+ kfree(part_nodes);
+
return nr_parts;
ofpart_fail:
@@ -136,6 +181,7 @@ ofpart_fail:
ofpart_none:
of_node_put(pp);
kfree(*pparts);
+ kfree(part_nodes);
*pparts = NULL;
return ret;
}