[RFC PATCH 2/7] lib: Add libxml2 support
Samuel Mendoza-Jonas
sam.mj at au1.ibm.com
Mon Nov 30 14:13:15 AEDT 2015
Definitions for attribute overrides on OpenPower machines will be read
from a static XML file written into the Skiroot initramfs. Add basic
support to parse an XML file using libxml2.
TODO: Update build rules to make libxml2 support optional
Signed-off-by: Samuel Mendoza-Jonas <sam.mj at au1.ibm.com>
---
lib/Makefile.am | 11 +++-
lib/types/types.c | 63 ++++++++++++++++++++++
lib/types/types.h | 3 ++
lib/xml/xml.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/xml/xml.h | 19 +++++++
5 files changed, 249 insertions(+), 2 deletions(-)
create mode 100644 lib/xml/xml.c
create mode 100644 lib/xml/xml.h
diff --git a/lib/Makefile.am b/lib/Makefile.am
index a2421a5..1d55914 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -18,7 +18,11 @@ noinst_LTLIBRARIES += $(core_lib)
lib_libpbcore_la_CPPFLAGS = \
$(AM_CPPFLAGS) \
- -DPREFIX='"$(prefix)"'
+ -DPREFIX='"$(prefix)"' \
+ `xml2-config --cflags`
+
+lib_libpbcore_la_LDFLAGS = \
+ `xml2-config --libs`
lib_libpbcore_la_SOURCES = \
lib/file/file.h \
@@ -41,6 +45,7 @@ lib_libpbcore_la_SOURCES = \
lib/process/process.h \
lib/types/types.c \
lib/types/types.h \
+ lib/types/types.c \
lib/talloc/talloc.c \
lib/talloc/talloc.h \
lib/system/system.c \
@@ -48,4 +53,6 @@ lib_libpbcore_la_SOURCES = \
lib/url/url.c \
lib/url/url.h \
lib/util/util.c \
- lib/util/util.h
+ lib/util/util.h \
+ lib/xml/xml.c \
+ lib/xml/xml.h
diff --git a/lib/types/types.c b/lib/types/types.c
index 63045e1..818c7b7 100644
--- a/lib/types/types.c
+++ b/lib/types/types.c
@@ -1,6 +1,8 @@
#include <string.h>
#include <types/types.h>
#include <i18n/i18n.h>
+#include <talloc/talloc.h>
+#include <log/log.h>
const char *ipmi_bootdev_display_name(enum ipmi_bootdev bootdev)
{
@@ -75,3 +77,64 @@ enum device_type find_device_type(const char *str)
return DEVICE_TYPE_UNKNOWN;
}
+/* Hostboot debugging */
+
+void dump_firmware_config(struct firmware_option *opts,
+ int n_opts, int level)
+{
+ unsigned int j;
+ int i;
+ char *prefix;
+
+ prefix = talloc_array(opts, char, level + 2);
+ prefix[0] = '>';
+ if (level) memset(&prefix[1], '\t', level);
+ prefix[level + 1] = '\0';
+
+ for (i = 0; i < n_opts; i++) {
+ if (opts[i].type == FIRMWARE_GROUP ) {
+ pb_log("%sGroup: %s\n", prefix, opts[i].name);
+ dump_firmware_config(opts[i].opts,
+ opts[i].n_opts, level + 1);
+ continue;
+ }
+
+ struct firmware_attr *attr = opts[i].attr;
+ if (opts[i].name)
+ pb_log("%sAttribute: %s\n", prefix, opts[i].name);
+ else
+ pb_log("%sUnnamed Attribute\n", prefix);
+ pb_log("%sid: %s\n", prefix, attr->id);
+ pb_log("%snumeric-id: %s\n", prefix, attr->numeric_id);
+ pb_log("%ssigned: %s\n", prefix, attr->is_signed ? "true" : "false");
+ pb_log("%ssize: %x\n", prefix, attr->size);
+
+ pb_log("%sdefault-val: %s\n", prefix, attr->value);
+ pb_log("%sdisplay-name: %s\n", prefix, attr->display_name);
+ pb_log("%sdescription: %s\n", prefix, attr->description);
+
+ if (attr->limit == LIMIT_NONE) {
+ pb_log("%sNo limit specified\n", prefix);
+ continue;
+ }
+
+ if (attr->limit == LIMIT_RANGE) {
+ pb_log("%sRange limit: <%d,%d>\n", prefix,
+ attr->range[0], attr->range[1]);
+ continue;
+ }
+
+ pb_log("%s%u enumerations specified\n",
+ prefix, attr->n_range);
+ for (j = 0; j < attr->n_range; j++) {
+ pb_log("%s\tdisplay-name: %s\n",
+ prefix, attr->enums[j].display_name);
+ pb_log("%s\tdescription: %s\n",
+ prefix, attr->enums[j].description);
+ pb_log("%s\tvalue (hex): %x\n",
+ prefix, attr->enums[j].value);
+ }
+ }
+
+ talloc_free(prefix);
+}
diff --git a/lib/types/types.h b/lib/types/types.h
index 8c9d552..dd3a849 100644
--- a/lib/types/types.h
+++ b/lib/types/types.h
@@ -217,4 +217,7 @@ struct config {
bool debug;
};
+void dump_firmware_config(struct firmware_option *opts,
+ int n_opts, int level);
+
#endif /* _TYPES_H */
diff --git a/lib/xml/xml.c b/lib/xml/xml.c
new file mode 100644
index 0000000..990b1bd
--- /dev/null
+++ b/lib/xml/xml.c
@@ -0,0 +1,155 @@
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <string.h>
+
+#include <talloc/talloc.h>
+#include <log/log.h>
+
+#include "xml/xml.h"
+
+xmlDocPtr readXMLFile(const char *path)
+{
+ xmlParserCtxtPtr ctxt;
+ xmlDocPtr doc = NULL;
+
+ if (!path)
+ goto out;
+
+ LIBXML_TEST_VERSION;
+
+ ctxt = xmlNewParserCtxt();
+ if (!ctxt)
+ goto out;
+
+ doc = xmlCtxtReadFile(ctxt, path, NULL, 0);
+ /*
+ * Future hostboot xmls will include or reference a DTD, which
+ * we should use
+ * doc = xmlCtxtReadFile(ctxt, path, NULL, XML_PARSE_DTDVALID);
+ */
+ if (!doc) {
+ pb_log("Failed to parse XML file '%s'\n", path);
+ goto out;
+ }
+
+ if (!ctxt->valid) {
+ pb_log("XML file '%s' failed DTD check\n", path);
+ xmlFreeDoc(doc);
+ doc = NULL;
+ }
+
+ xmlFreeParserCtxt(ctxt);
+out:
+ return doc;
+ //on some error paths we may as well cleanup the library
+}
+
+xmlNodePtr findXMLRoot(xmlDocPtr doc, const char *name)
+{
+ xmlNodePtr node, root = NULL;
+
+ for (node = xmlDocGetRootElement(doc); node; node = node->next)
+ if (node->type == XML_ELEMENT_NODE)
+ if (!xmlStrcmp(node->name, (const xmlChar *)name)) {
+ root = node;
+ break;
+ }
+ return root;
+}
+
+
+/* Return first child node matching name */
+xmlNodePtr findChildNode(xmlNodePtr root, xmlElementType type,
+ const char *name)
+{
+ xmlNodePtr cur;
+
+ for (cur = root->children; cur; cur = cur->next)
+ if (!type || cur->type == type)
+ if (!xmlStrcmp(cur->name, (const xmlChar *)name))
+ return cur;
+ return NULL;
+}
+
+/*
+ * We probably won't end up looping through attributes like we do with
+ * elements since they will be fairly specific, but here's an
+ * illustrative example
+ */
+void printAttrs(xmlDocPtr doc, xmlNodePtr node, const char *prefix)
+{
+ xmlAttrPtr attr;
+ xmlChar *key = NULL;
+
+ for (attr = node->properties; attr; attr = attr->next) {
+ key = xmlNodeListGetString(doc, attr->xmlChildrenNode, 1);
+ pb_log("%s'%s'->'%s'\n", prefix, attr->name, key);
+ xmlFree(key);
+ }
+}
+
+char *nodeAttribute(void *ctx, xmlNodePtr node, const char *name)
+{
+ xmlChar *tmp;
+ char *attr;
+
+ tmp = xmlGetProp(node, (xmlChar *) name);
+ attr = talloc_strdup(ctx, (char *) tmp);
+
+ xmlFree(tmp);
+ return attr;
+}
+
+
+/* Allocate content under context, return NULL for whitespace-only results */
+char *nodeContent(void *ctx, xmlDocPtr doc, xmlNodePtr node)
+{
+ char *content;
+ xmlChar *tmp = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
+ /* xmlNodeGetContent aggregates empty fields */
+
+ content = talloc_strdup(ctx, (char *)tmp);
+ xmlFree(tmp);
+
+ return content;
+}
+
+bool hasChildren(xmlNodePtr node, xmlElementType type)
+{
+ xmlNodePtr cur;
+ int n = 0;
+
+ for (cur = node->children; cur; cur = cur->next)
+ if (!type || cur->type == type)
+ n++;
+
+ return n;
+}
+
+/* Return child nodes, optionally filtering by type */
+int nodeChildren(void *ctx, xmlNodePtr **nodes, xmlNodePtr node,
+ xmlElementType type)
+{
+ xmlNodePtr cur, *children = NULL;
+ int n = 0;
+
+ for (cur = node->children; cur; cur = cur->next) {
+ if (!type || cur->type == type) {
+ children = talloc_realloc(ctx, children,
+ xmlNodePtr, n + 1);
+ children[n++] = cur;
+ }
+ }
+
+ *nodes = children;
+ return n;
+}
+
+/*
+ * This should only be called once we are completely finished with the library.
+ */
+void finaliseXML(xmlDocPtr doc)
+{
+ xmlFreeDoc(doc);
+ xmlCleanupParser();
+}
diff --git a/lib/xml/xml.h b/lib/xml/xml.h
new file mode 100644
index 0000000..91cc8d3
--- /dev/null
+++ b/lib/xml/xml.h
@@ -0,0 +1,19 @@
+#ifndef _XML_H
+#define _XML_H
+
+#include <libxml/tree.h>
+
+xmlDocPtr readXMLFile(const char *path);
+xmlNodePtr findXMLRoot(xmlDocPtr doc, const char *root_name);
+xmlNodePtr findChildNode(xmlNodePtr root, xmlElementType type,
+ const char *name);
+int nodeChildren(void *ctx, xmlNodePtr **nodes, xmlNodePtr node,
+ xmlElementType type);
+bool hasChildren(xmlNodePtr node, xmlElementType type);
+
+char *nodeContent(void *ctx, xmlDocPtr doc, xmlNodePtr node);
+char *nodeAttribute(void *ctx, xmlNodePtr node, const char *name);
+void printAttrs(xmlDocPtr doc, xmlNodePtr node, const char *prefix);
+void finaliseXML(xmlDocPtr doc);
+
+#endif /* _XML_H */
--
2.6.2
More information about the Petitboot
mailing list