@@ -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;
+}
@@ -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
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(+)