summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorFurquan Shaikh <furquan@google.com>2021-08-23 23:23:23 -0700
committerTim Wawrzynczak <twawrzynczak@chromium.org>2021-09-01 19:20:05 +0000
commitb9c22e09651a7a07af7b2869a91f2d100b08f71b (patch)
tree9f27156d7ee86866c45579be3c94176b8acf5dee /util
parentbf42db6eb7f6af80a6f384c40e19235d4c6dad2c (diff)
util/sconfig: Compare probe conditions for override device match
When the override functionality looks for device match, check that the probe list for both the devices matches exactly if probe list exists for the base device. This ensures that if there are two devices with same identity (e.g. I2C address or USB port #) but using different properties (registers) controlled by different probe statements, then the two devices are not incorrectly matched as the same device. The check for base device having a probe list is performed before comparing the probe lists because a base device might not really have any probe requirements at all. So, when overriding such a device, there is no need to check for the probe list match. BUG=b:187193527 TEST=Verified by adding two I2C devices in the override tree with the same I2C address and chip but different probe statements and confirmed that both the devices are present in generated static.c file. Change-Id: Ib18868b336cf4ffc9aa38aee7c6f333a35d32fce Signed-off-by: Furquan Shaikh <furquan@google.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/57111 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org> Reviewed-by: Weimin Wu <wuweimin@huaqin.corp-partner.google.com> Reviewed-by: Karthik Ramasubramanian <kramasub@google.com>
Diffstat (limited to 'util')
-rw-r--r--util/sconfig/main.c82
1 files changed, 75 insertions, 7 deletions
diff --git a/util/sconfig/main.c b/util/sconfig/main.c
index 91c079a624..f7d1d1099f 100644
--- a/util/sconfig/main.c
+++ b/util/sconfig/main.c
@@ -552,19 +552,28 @@ static void append_fw_config_probe_to_dev(struct device *dev, struct fw_config_p
}
}
-void add_fw_config_probe(struct bus *bus, const char *field, const char *option)
+static int check_probe_exists(struct fw_config_probe *probe, const char *field,
+ const char *option)
{
- struct fw_config_probe *probe;
-
- probe = bus->dev->probe;
while (probe) {
if (!strcmp(probe->field, field) && !strcmp(probe->option, option)) {
- printf("ERROR: fw_config probe %s:%s already exists\n", field, option);
- exit(1);
+ return 1;
}
probe = probe->next;
}
+ return 0;
+}
+
+void add_fw_config_probe(struct bus *bus, const char *field, const char *option)
+{
+ struct fw_config_probe *probe;
+
+ if (check_probe_exists(bus->dev->probe, field, option)) {
+ printf("ERROR: fw_config probe %s:%s already exists\n", field, option);
+ exit(1);
+ }
+
probe = S_ALLOC(sizeof(*probe));
probe->field = field;
probe->option = option;
@@ -1479,6 +1488,56 @@ static void parse_devicetree(const char *file, struct bus *parent)
fclose(filec);
}
+static int device_probe_count(struct fw_config_probe *probe)
+{
+ int count = 0;
+ while (probe) {
+ probe = probe->next;
+ count++;
+ }
+
+ return count;
+}
+
+/*
+ * When overriding devices, use the following rules:
+ * 1. If probe count matches and:
+ * a. Entire probe list matches for both devices -> Same device, override.
+ * b. No probe entries match -> Different devices, do not override.
+ * c. Partial list matches -> Bad device tree entries, fail build.
+ *
+ * 2. If probe counts do not match and:
+ * a. No probe entries match -> Different devices, do not override.
+ * b. Partial list matches -> Bad device tree entries, fail build.
+ */
+static int device_probes_match(struct device *a, struct device *b)
+{
+ struct fw_config_probe *a_probe = a->probe;
+ struct fw_config_probe *b_probe = b->probe;
+ int a_probe_count = device_probe_count(a_probe);
+ int b_probe_count = device_probe_count(b_probe);
+ int match_count = 0;
+
+ while (a_probe) {
+ if (check_probe_exists(b_probe, a_probe->field, a_probe->option))
+ match_count++;
+ a_probe = a_probe->next;
+ }
+
+ if ((a_probe_count == b_probe_count) && (a_probe_count == match_count))
+ return 1;
+
+ if (match_count) {
+ printf("ERROR: devices with overlapping probes: ");
+ printf(a->path, a->path_a, a->path_b);
+ printf(b->path, b->path_a, b->path_b);
+ printf("\n");
+ exit(1);
+ }
+
+ return 0;
+}
+
/*
* Match device nodes from base and override tree to see if they are the same
* node.
@@ -1803,7 +1862,16 @@ static void override_devicetree(struct bus *base_parent,
/* Look for a matching device in base tree. */
for (base_child = base_parent->children;
base_child; base_child = base_child->sibling) {
- if (device_match(base_child, override_child))
+ if (!device_match(base_child, override_child))
+ continue;
+ /* If base device has no probe statement, nothing else to compare. */
+ if (base_child->probe == NULL)
+ break;
+ /*
+ * If base device has probe statements, ensure that all probe conditions
+ * match for base and override device.
+ */
+ if (device_probes_match(base_child, override_child))
break;
}