[PATCH 2/3] discovery: Add helper functions to read ELF notes
Maxiwell S. Garcia
maxiwell at linux.ibm.com
Tue Sep 10 00:19:07 AEST 2019
The libelf has low level functions to access the ELF structures.
This commit adds two external higher level functions:
elf_open_image():
- Get the ELF structure from a binary;
elf_getnote_desc()
- Get the ELF note 'descriptor' using both namespace and ELF type.
The definitions used in the 'elf.h' was taken from linux source code:
- arch/powerpc/include/asm/elfnote.h
- arch/powerpc/kernel/note.S
Signed-off-by: Maxiwell S. Garcia <maxiwell at linux.ibm.com>
---
discover/Makefile.am | 4 ++-
discover/elf.c | 86 ++++++++++++++++++++++++++++++++++++++++++++
discover/elf.h | 29 +++++++++++++++
3 files changed, 118 insertions(+), 1 deletion(-)
create mode 100644 discover/elf.c
create mode 100644 discover/elf.h
diff --git a/discover/Makefile.am b/discover/Makefile.am
index e2d0e93..0135cc3 100644
--- a/discover/Makefile.am
+++ b/discover/Makefile.am
@@ -51,7 +51,9 @@ discover_pb_discover_SOURCES = \
discover/kboot-parser.c \
discover/yaboot-parser.c \
discover/pxe-parser.c \
- discover/syslinux-parser.c
+ discover/syslinux-parser.c \
+ discover/elf.c \
+ discover/elf.h
discover_pb_discover_LDADD = \
discover/grub2/grub2-parser.ro \
diff --git a/discover/elf.c b/discover/elf.c
new file mode 100644
index 0000000..8c2711e
--- /dev/null
+++ b/discover/elf.c
@@ -0,0 +1,86 @@
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include <log/log.h>
+#include "elf.h"
+
+Elf *elf_open_image(const char *image)
+{
+ int fd;
+ Elf *elf = NULL;
+ int err;
+
+ if (!image) {
+ pb_log_fn("kernel image path is null\n");
+ return NULL;
+ }
+
+ if ((elf_version(EV_CURRENT) == EV_NONE) ||
+ ((fd = open(image, O_RDONLY, 0)) == -1) ||
+ (!(elf = elf_begin(fd, ELF_C_READ, NULL)))) {
+ err = elf_errno();
+ if (err)
+ pb_log_fn("failed to read %s elf: %s\n",
+ image, elf_errmsg(err));
+ }
+
+ return elf;
+}
+
+static bool elf_getnote_offset(Elf_Data * const edata,
+ const char *namespace,
+ const uint32_t type, GElf_Nhdr *nhdr,
+ size_t *n_off, size_t *d_off)
+{
+ size_t off = 0;
+ size_t next;
+
+ /* Iterate through notes */
+ while ((next = gelf_getnote(edata, off, nhdr, n_off, d_off)) > 0) {
+ char *note_ns = (char *) edata->d_buf + (*n_off);
+ if ((strcmp(note_ns, namespace) == 0) && (nhdr->n_type == type))
+ return true;
+
+ off = next;
+ }
+ return false;
+}
+
+void *elf_getnote_desc(Elf *elf,
+ const char *namespace,
+ uint32_t type)
+{
+ Elf_Scn *scn = NULL;
+ Elf_Data *edata = NULL;
+ GElf_Shdr shdr;
+ GElf_Nhdr nhdr;
+
+ size_t n_off;
+ size_t d_off;
+ void *desc = NULL;
+
+ if (!elf || !namespace)
+ return NULL;
+
+ /* Iterate through sections */
+ while ((scn = elf_nextscn(elf, scn))) {
+ gelf_getshdr(scn, &shdr);
+
+ /* ELF might have more than one SHT_NOTE section but
+ only one has the 'namespace' note */
+ if (shdr.sh_type == SHT_NOTE) {
+ edata = elf_getdata(scn, NULL);
+ if (elf_getnote_offset(edata, namespace, type,
+ &nhdr, &n_off, &d_off)) {
+ desc = calloc(nhdr.n_descsz, sizeof(char));
+ memcpy(desc, edata->d_buf + d_off,
+ nhdr.n_descsz);
+ break;
+ }
+ }
+ }
+
+ return desc;
+}
+
diff --git a/discover/elf.h b/discover/elf.h
new file mode 100644
index 0000000..742b791
--- /dev/null
+++ b/discover/elf.h
@@ -0,0 +1,29 @@
+#ifndef _PB_ELF_H
+#define _PB_ELF_H
+
+#include <elfutils/libdw.h>
+#include <libelf.h>
+
+/*
+ * The PowerPC namespace in an ELF Note of the kernel binary is used to store
+ * capabilities and information which can be used by a bootloader or userland
+ *
+ * docs: Documentation/powerpc/elfnote.rst
+ */
+#define POWERPC_ELFNOTE_NAMESPACE "PowerPC"
+
+/*
+ * The capabilities supported/required by the kernel
+ * This type uses a bitmap as "desc" field.
+ */
+#define PPC_ELFNOTE_CAPABILITIES 0x1
+
+/* bitmap fields: */
+#define PPCCAP_ULTRAVISOR_BIT 0x1
+
+Elf *elf_open_image(const char *image);
+void *elf_getnote_desc(Elf *elf,
+ const char *namespace,
+ uint32_t type);
+
+#endif /* _PB_ELF_H */
--
2.20.1
More information about the Petitboot
mailing list