diff mbox series

[v2] libpdbg: Add api for attribute read and write

Message ID 20200304065357.205990-1-amitay@ozlabs.org
State Superseded
Headers show
Series [v2] libpdbg: Add api for attribute read and write | expand

Checks

Context Check Description
snowpatch_ozlabs/apply_patch warning Failed to apply on branch master (8b4611b5d8e7e2279fe4aa80c892fcfe10aa398d)
snowpatch_ozlabs/apply_patch fail Failed to apply to any branch

Commit Message

Amitay Isaacs March 4, 2020, 6:53 a.m. UTC
There are 2 apis for reading and writing depending on the data type of
attribute value.

1. Simple - Array of integer data type (1, 2, 4, 8 bytes)
2. Complex - Stream of integer data type (1, 2, 4, 8 bytes)

Signed-off-by: Amitay Isaacs <amitay@ozlabs.org>
---
 libpdbg/device.c  | 199 ++++++++++++++++++++++++++++++++++++++++++++++
 libpdbg/libpdbg.h |  75 +++++++++++++++++
 2 files changed, 274 insertions(+)
diff mbox series

Patch

diff --git a/libpdbg/device.c b/libpdbg/device.c
index 604cddb..a57af1c 100644
--- a/libpdbg/device.c
+++ b/libpdbg/device.c
@@ -755,3 +755,202 @@  struct pdbg_target *pdbg_target_root(void)
 {
 	return pdbg_dt_root;
 }
+
+bool pdbg_target_set_attribute(struct pdbg_target *target, const char *name, const void *val, uint32_t count, uint32_t size)
+{
+	void *buf;
+	size_t total_size = count * size;
+	uint32_t i;
+	bool ok;
+
+	buf = malloc(total_size);
+	if (!buf)
+		return false;
+
+	if (size == 1) {
+		memcpy(buf, val, total_size);
+
+	} else if (size == 2) {
+		uint16_t *b = (uint16_t *)buf;
+		uint16_t *v = (uint16_t *)val;
+
+		for (i = 0; i < count; i++)
+			b[i] = htobe16(v[i]);
+
+	} else if (size == 4) {
+		uint32_t *b = (uint32_t *)buf;
+		uint32_t *v = (uint32_t *)val;
+
+		for (i = 0; i < count; i++)
+			b[i] = htobe32(v[i]);
+
+	} else if (size == 8) {
+		uint64_t *b = (uint64_t *)buf;
+		uint64_t *v = (uint64_t *)val;
+
+		for (i = 0; i < count; i++)
+			b[i] = htobe64(v[i]);
+
+	} else {
+		free(buf);
+		return false;
+	}
+
+	ok = pdbg_target_set_property(target, name, buf, total_size);
+	free(buf);
+
+	return ok;
+}
+
+bool pdbg_target_get_attribute(struct pdbg_target *target, const char *name, void *val, uint32_t count, uint32_t size)
+{
+	const void *buf;
+	size_t total_size;
+	uint32_t i;
+
+	buf = pdbg_target_property(target, name, &total_size);
+	if (!buf)
+		return false;
+
+	if (total_size != count * size)
+		return false;
+
+	if (size == 1) {
+		memcpy(val, buf, total_size);
+
+	} else if (size == 2) {
+		uint16_t *b = (uint16_t *)buf;
+		uint16_t *v = (uint16_t *)val;
+
+		for (i = 0; i < count; i++)
+			v[i] = be16toh(b[i]);
+
+	} else if (size == 4) {
+		uint32_t *b = (uint32_t *)buf;
+		uint32_t *v = (uint32_t *)val;
+
+		for (i = 0; i < count; i++)
+			v[i] = be32toh(b[i]);
+
+	} else if (size == 8) {
+		uint64_t *b = (uint64_t *)buf;
+		uint64_t *v = (uint64_t *)val;
+
+		for (i = 0; i < count; i++)
+			v[i] = be64toh(b[i]);
+
+	} else {
+		return false;
+	}
+
+	return true;
+}
+
+bool pdbg_target_set_attribute_packed(struct pdbg_target *target, const char *name, const char *spec, const void *val, uint32_t size)
+{
+	void *buf;
+	size_t pos, i;
+	bool ok;
+
+	if (!spec || spec[0] == '\0')
+		return false;
+
+	buf = malloc(size);
+	if (!buf)
+		return false;
+
+	pos = 0;
+	for (i=0; i<strlen(spec); i++) {
+		char ch = spec[i];
+
+		if (ch == '1') {
+			uint8_t *b = (uint8_t *)buf + pos;
+			uint8_t *v = (uint8_t *)val + pos;
+
+			*b = *v;
+			pos += 1;
+
+		} else if (ch == '2') {
+			uint16_t *b = (uint16_t *)((uint8_t *)buf + pos);
+			uint16_t *v = (uint16_t *)((uint8_t *)val + pos);
+
+			*b = htobe16(*v);
+			pos += 2;
+
+		} else if (ch == '4') {
+			uint32_t *b = (uint32_t *)((uint8_t *)buf + pos);
+			uint32_t *v = (uint32_t *)((uint8_t *)val + pos);
+
+			*b = htobe32(*v);
+			pos += 4;
+
+		} else if (ch == '8') {
+			uint64_t *b = (uint64_t *)((uint8_t *)buf + pos);
+			uint64_t *v = (uint64_t *)((uint8_t *)val + pos);
+
+			*b = htobe64(*v);
+			pos += 8;
+
+		} else {
+			free(buf);
+			return false;
+		}
+	}
+
+	ok = pdbg_target_set_property(target, name, buf, size);
+	free(buf);
+
+	return ok;
+}
+
+bool pdbg_target_get_attribute_packed(struct pdbg_target *target, const char *name, const char *spec, void *val, uint32_t size)
+{
+	const void *buf;
+	size_t total_size, pos, i;
+
+	buf = pdbg_target_property(target, name, &total_size);
+	if (!buf)
+		return false;
+
+	if (total_size != size)
+		return false;
+
+	pos = 0;
+	for (i=0; i<strlen(spec); i++) {
+		char ch = spec[i];
+
+		if (ch == '1') {
+			uint8_t *b = (uint8_t *)buf + pos;
+			uint8_t *v = (uint8_t *)val + pos;
+
+			*v = *b;
+			pos += 1;
+
+		} else if (ch == '2') {
+			uint16_t *b = (uint16_t *)((uint8_t *)buf + pos);
+			uint16_t *v = (uint16_t *)((uint8_t *)val + pos);
+
+			*v = be16toh(*b);
+			pos += 2;
+
+		} else if (ch == '4') {
+			uint32_t *b = (uint32_t *)((uint8_t *)buf + pos);
+			uint32_t *v = (uint32_t *)((uint8_t *)val + pos);
+
+			*v = be32toh(*b);
+			pos += 4;
+
+		} else if (ch == '8') {
+			uint64_t *b = (uint64_t *)((uint8_t *)buf + pos);
+			uint64_t *v = (uint64_t *)((uint8_t *)val + pos);
+
+			*v = be64toh(*b);
+			pos += 8;
+
+		} else {
+			return false;
+		}
+	}
+
+	return true;
+}
diff --git a/libpdbg/libpdbg.h b/libpdbg/libpdbg.h
index 1fc7ef4..ceb28e9 100644
--- a/libpdbg/libpdbg.h
+++ b/libpdbg/libpdbg.h
@@ -312,6 +312,81 @@  bool pdbg_target_set_property(struct pdbg_target *target, const char *name, cons
  */
 const void *pdbg_target_property(struct pdbg_target *target, const char *name, size_t *size);
 
+/**
+ * @brief Overwrite the value of given attribute in device tree
+ *
+ * The attributes are treated as 1, 2, 4, or 8 byte integer arrays.
+ *
+ * @param[in] target pdbg_target to set the attribute on
+ * @param[in] name name of the attribute to set
+ * @param[in] val value of the attribute to set
+ * @param[in] count Number of elements in the buffer
+ * @param[in] size Size of element
+ * @return true on success, false on failure
+ *
+ * This function will update the attribute value provided the count of
+ * elements and the size of element matches.
+ */
+bool pdbg_target_set_attribute(struct pdbg_target *target, const char *name, const void *val, uint32_t count, uint32_t size);
+
+/**
+ * @brief Get the value of the given attribute from device tree
+ *
+ * The attributes are treated as 1, 2, 4, or 8 byte integer arrays.
+ *
+ * @param[in] target pdbg_target to get the attribute from
+ * @param[in] name name of the attribute to get
+ * @param[out] val value of the attribute
+ * @param[in] count Number of elements in the buffer
+ * @param[in] size Size of element
+ * @return true on success, false on failure
+ *
+ * This function will copy the attribute value in the given buffer, provided
+ * the count of elements and the size of element matches.
+ */
+bool pdbg_target_get_attribute(struct pdbg_target *target, const char *name, void *val, uint32_t count, uint32_t size);
+
+/**
+ * @brief Overwrite the value of given attribute in device tree
+ *
+ * The attribute value is treated as a packed stream of 1, 2, 4, or 8 byte
+ * integers.  The specification describes how the integers are packed.
+ *
+ * Example:
+ *    A stream of uint32_t, uint8_t, uint16_t, uint32_t is specified as
+ *    "4124".
+ *
+ * @param[in] target pdbg_target to set the attribute on
+ * @param[in] name name of the attribute to set
+ * @param[in] spec specification of packed integers
+ * @param[in] val value of the attribute to set
+ * @param[in] size total size of the value
+ * @return true on success, false on failure
+ *
+ * This function will update the attribute value provided the size matches.
+ */
+bool pdbg_target_set_attribute_packed(struct pdbg_target *target, const char *name, const char *spec, const void *val, uint32_t size);
+
+/**
+ * @brief Get the value of the given attribute from device tree
+ *
+ * The attribute value is treated as a packed stream of 1, 2, 4, or 8 byte
+ * integers.  The specification describes how the integers are packed.
+ *
+ * @see pdbg_target_set_attribute_packed
+ *
+ * @param[in] target pdbg_target to get the attribute from
+ * @param[in] name name of the attribute to get
+ * @param[in] spec specification of packed integers
+ * @param[out] val value of the attribute
+ * @param[in] size total size of the value
+ * @return true on success, false on failure
+ *
+ * This function will copy the attribute value in the given buffer, provided
+ * the specification matches.
+ */
+bool pdbg_target_get_attribute_packed(struct pdbg_target *target, const char *name, const char *spec, void *val, uint32_t size);
+
 /**
  * @brief Get the given property value as a uint32_t
  * @param[in] target pdbg_target to get the property from