[coreboot-gerrit] Patch set updated for coreboot: cbfstool: Extract payload in ELF
Antonello Dettori (dev@dettori.io)
gerrit at coreboot.org
Fri Jun 10 11:46:22 CEST 2016
Antonello Dettori (dev at dettori.io) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15139
-gerrit
commit 8496dfa51cfe7e528f85dfe57d5bd22ac218fe84
Author: Antonello Dettori <dettori.an at gmail.com>
Date: Thu Jun 9 12:35:36 2016 +0200
cbfstool: Extract payload in ELF
Implement function that automatically converts a SELF payload,
extracted from the CBFS, into an ELF file.
The code has been tested on the following payloads:
Working: SeaBIOS, nvramcui, coreinfo and tint
Currently not working: grub
Change-Id: I51599e65419bfa4ada8fe24b119acb20c9936227
Signed-off-by: Antonello Dettori <dettori.an at gmail.com>
---
util/cbfstool/cbfs_image.c | 154 +++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 150 insertions(+), 4 deletions(-)
diff --git a/util/cbfstool/cbfs_image.c b/util/cbfstool/cbfs_image.c
index 0e20c80..0ba7c94 100644
--- a/util/cbfstool/cbfs_image.c
+++ b/util/cbfstool/cbfs_image.c
@@ -949,6 +949,151 @@ static int cbfs_stage_make_elf(struct buffer *buff, uint32_t arch)
return 0;
}
+static int cbfs_payload_make_elf(struct buffer *buff, uint32_t arch)
+{
+ Elf64_Ehdr ehdr;
+ Elf64_Shdr shdr;
+ struct cbfs_payload_segment *segs;
+ struct elf_writer *ew;
+ struct buffer elf_out;
+ size_t empty_sz;
+ int segments = 0;
+
+ /* Count the number of segments inside buffer */
+ while (true) {
+ uint32_t payload_type = 0;
+
+ memcpy(&payload_type, buff->data +
+ sizeof(struct cbfs_payload_segment) * segments,
+ sizeof(PAYLOAD_SEGMENT_CODE));
+ payload_type = ntohl(payload_type);
+
+ if (payload_type == PAYLOAD_SEGMENT_CODE) {
+ segments++;
+ } else if (payload_type == PAYLOAD_SEGMENT_DATA) {
+ segments++;
+ } else if (payload_type == PAYLOAD_SEGMENT_BSS) {
+ segments++;
+ } else if (payload_type == PAYLOAD_SEGMENT_PARAMS) {
+ segments++;
+ } else if (payload_type == PAYLOAD_SEGMENT_ENTRY) {
+ /* The last segment in a payload is always ENTRY as
+ * specified by the parse_elf_to_payload() function.
+ * Therefore there is no need to continue looking for
+ * segments.*/
+ segments++;
+ break;
+ } else {
+ ERROR("Unknown payload segment type: %x\n",
+ payload_type);
+ return -1;
+ }
+
+ }
+
+ segs = malloc(segments * sizeof(*segs));
+
+ /* Decode xdr segments */
+ for (int i = 0; i < segments; i++) {
+ struct cbfs_payload_segment *serialized_seg = buffer_get(buff);
+
+ xdr_get_seg(&segs[i], &serialized_seg[i]);
+ }
+
+ if (init_elf_from_arch(&ehdr, arch))
+ return -1;
+
+ ehdr.e_entry = segs[segments-1].load_addr;
+
+ ew = elf_writer_init(&ehdr);
+ if (ew == NULL) {
+ ERROR("Unable to init ELF writer.\n");
+ return -1;
+ }
+
+ for (int i = 0; i < segments; i++) {
+ struct buffer tbuff;
+
+ memset(&shdr, 0, sizeof(shdr));
+ char *name = NULL;
+
+ if (segs[i].type == PAYLOAD_SEGMENT_CODE) {
+ shdr.sh_type = SHT_PROGBITS;
+ shdr.sh_flags = SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR;
+ shdr.sh_addr = segs[i].load_addr;
+ shdr.sh_size = segs[i].len;
+ empty_sz = segs[i].mem_len - segs[i].len;
+ name = strdup(".text");
+ buffer_splice(&tbuff, buff, segs[i].offset,
+ segs[i].len);
+ } else if (segs[i].type == PAYLOAD_SEGMENT_DATA) {
+ shdr.sh_type = SHT_PROGBITS;
+ shdr.sh_flags = SHF_ALLOC | SHF_WRITE;
+ shdr.sh_addr = segs[i].load_addr;
+ shdr.sh_size = segs[i].len;
+ empty_sz = segs[i].mem_len - segs[i].len;
+ name = strdup(".data");
+ buffer_splice(&tbuff, buff, segs[i].offset,
+ segs[i].len);
+ } else if (segs[i].type == PAYLOAD_SEGMENT_BSS) {
+ shdr.sh_type = SHT_NOBITS;
+ shdr.sh_flags = SHF_ALLOC | SHF_WRITE;
+ shdr.sh_addr = segs[i].load_addr;
+ shdr.sh_size = segs[i].len;
+ name = strdup(".bss");
+ buffer_splice(&tbuff, buff, 0, 0);
+ } else if (segs[i].type == PAYLOAD_SEGMENT_PARAMS) {
+ shdr.sh_type = SHT_NOTE;
+ shdr.sh_flags = 0;
+ shdr.sh_size = segs[i].len;
+ name = strdup(".note.pinfo");
+ buffer_splice(&tbuff, buff, segs[i].offset,
+ segs[i].len);
+ } else if (segs[i].type == PAYLOAD_SEGMENT_ENTRY) {
+ break;
+ }
+
+
+ if (elf_writer_add_section(ew, &shdr, &tbuff, name)) {
+ ERROR("Unable to add ELF section: %s\n", name);
+ elf_writer_destroy(ew);
+ return -1;
+ }
+
+ if (empty_sz != 0) {
+ struct buffer b;
+
+ buffer_init(&b, NULL, NULL, 0);
+ memset(&shdr, 0, sizeof(shdr));
+ shdr.sh_type = SHT_NOBITS;
+ shdr.sh_flags = SHF_WRITE | SHF_ALLOC;
+ shdr.sh_addr = segs[i].load_addr + segs[i].len;
+ shdr.sh_size = empty_sz;
+ name = strdup(".empty");
+ if (elf_writer_add_section(ew, &shdr, &b, name)) {
+ ERROR("Unable to add ELF section: %s\n", name);
+ elf_writer_destroy(ew);
+ return -1;
+ }
+ }
+
+ }
+
+ if (elf_writer_serialize(ew, &elf_out)) {
+ ERROR("Unable to create ELF file from stage.\n");
+ elf_writer_destroy(ew);
+ return -1;
+ }
+
+ /* Flip buffer with the created ELF one. */
+ buffer_delete(buff);
+ *buff = elf_out;
+
+ elf_writer_destroy(ew);
+
+ return 0;
+}
+
int cbfs_export_entry(struct cbfs_image *image, const char *entry_name,
const char *filename, uint32_t arch)
{
@@ -973,10 +1118,6 @@ int cbfs_export_entry(struct cbfs_image *image, const char *entry_name,
entry_name, cbfs_get_entry_addr(image, entry),
get_cbfs_entry_type_name(ntohl(entry->type)), decompressed_size);
- if (ntohl(entry->type) == CBFS_COMPONENT_PAYLOAD) {
- WARN("Payloads are extracted in SELF format.\n");
- }
-
buffer_init(&buffer, strdup("(cbfs_export_entry)"), NULL, 0);
buffer.data = malloc(decompressed_size);
@@ -999,6 +1140,11 @@ int cbfs_export_entry(struct cbfs_image *image, const char *entry_name,
buffer_delete(&buffer);
return -1;
}
+ } else if (ntohl(entry->type) == CBFS_COMPONENT_PAYLOAD) {
+ if (cbfs_payload_make_elf(&buffer, arch)) {
+ buffer_delete(&buffer);
+ return -1;
+ }
}
if (buffer_write_file(&buffer, filename) != 0) {
More information about the coreboot-gerrit
mailing list