Michał Żygowski has uploaded this change for review. ( https://review.coreboot.org/27957
Change subject: Added multiboot support to cbfstool and made changes to behaviour for cbfs add-payload ......................................................................
Added multiboot support to cbfstool and made changes to behaviour for cbfs add-payload
* modified messaging and logic with respect to different payload types: - tries multiboot if neither ELF nor UEFI - then tries bzImage
* added check for Linux header in bzImage * change ERROR level message if stage file not in ELF format (reduced to INFO)
Note: multiboot support limited to obtaining load location and entry point
Change-Id: Iaeb808e8750ad81bdf8c4daedb0d91e961eebb70 Signed-off-by: Paul Roberts paul.c.roberts@ntlworld.com --- M util/cbfstool/cbfs-mkpayload.c M util/cbfstool/cbfs-payload-linux.c M util/cbfstool/cbfstool.c M util/cbfstool/common.h 4 files changed, 123 insertions(+), 2 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/57/27957/1
diff --git a/util/cbfstool/cbfs-mkpayload.c b/util/cbfstool/cbfs-mkpayload.c index d6c10ad..8df52d9 100644 --- a/util/cbfstool/cbfs-mkpayload.c +++ b/util/cbfstool/cbfs-mkpayload.c @@ -454,3 +454,104 @@
return 0; } + +#define MULTIBOOT_MAGIC 0x1BADB002 + +struct multiboot_header { + uint32_t magic; + uint32_t flags; + uint32_t checksum; + uint32_t header_addr; + uint32_t load_addr; + uint32_t load_end_addr; + uint32_t bss_end_addr; + uint32_t entry_addr; +}; + +static int find_multiboot_header(const struct buffer *input, + struct multiboot_header *mboot_hdr) +{ + int i; + + for (i = 0; i < 8192; i += sizeof(uint32_t)) { + uint32_t sum; + struct buffer in; + + buffer_clone(&in, input); + buffer_seek(&in, i); + + mboot_hdr->magic = xdr_le.get32(&in); + + if (mboot_hdr->magic != MULTIBOOT_MAGIC) + continue; + + mboot_hdr->flags = xdr_le.get32(&in); + mboot_hdr->checksum = xdr_le.get32(&in); + + sum = mboot_hdr->magic + mboot_hdr->flags + mboot_hdr->checksum; + + if (sum != 0) { + WARN("Multiboot header found @ %d. Checksum invalid\n", + i); + continue; + } + + mboot_hdr->header_addr = xdr_le.get32(&in); + mboot_hdr->load_addr = xdr_le.get32(&in); + mboot_hdr->load_end_addr = xdr_le.get32(&in); + mboot_hdr->bss_end_addr = xdr_le.get32(&in); + mboot_hdr->entry_addr = xdr_le.get32(&in); + + return i; + } + + return -1; +} + +int parse_multiboot_to_payload(const struct buffer *input, + struct buffer *output, enum comp_algo algo) +{ + int header_offset; + struct multiboot_header mboot_hdr; + uint32_t end_addr; + + + header_offset = find_multiboot_header(input, &mboot_hdr); + + if (header_offset < 0) { + WARN("No valid multiboot header found.\n"); + return -1; + } + + /* No runtime boot information supported. */ + if (mboot_hdr.flags & ((1 << 2) | (1 << 1))) { + WARN("No multiboot runtime boot information supported: %x.\n", + mboot_hdr.flags); + return -1; + } + + if (!(mboot_hdr.flags & (1 << 16))) { + WARN("No multiboot load information available: %x.\n", + mboot_hdr.flags); + return -1; + } + + end_addr = mboot_hdr.load_end_addr; + if (!end_addr) + end_addr = mboot_hdr.load_addr + input->size; + + /* Support full file load only. */ + if (header_offset + mboot_hdr.load_addr != mboot_hdr.header_addr || + end_addr - mboot_hdr.load_addr != input->size) { + WARN("Multiboot payload loading only supports full file.\n"); + return -1; + } + + INFO("Compatible Multiboot payload found. load address:" + " 0x%x entry: 0x%x\n",mboot_hdr.load_addr,mboot_hdr.entry_addr); + return parse_flat_binary_to_payload(input, + output, + mboot_hdr.load_addr, + mboot_hdr.entry_addr, + algo); +} diff --git a/util/cbfstool/cbfs-payload-linux.c b/util/cbfstool/cbfs-payload-linux.c index 6b4bf27..8183925 100644 --- a/util/cbfstool/cbfs-payload-linux.c +++ b/util/cbfstool/cbfs-payload-linux.c @@ -242,6 +242,19 @@
params.loader_type = 0xff; /* Unregistered Linux loader */
+ /* Check for signatures and determine version */ + if ( hdr->boot_sector_magic != 0xAA55 ) { + WARN("bzImage missing 55AA signature\n"); + return -1; + } + if ( (hdr->header_magic[0] != 'H')|| + (hdr->header_magic[1] != 'd')|| + (hdr->header_magic[2] != 'r')|| + (hdr->header_magic[3] != 'S')){ + WARN("bzImage missing HdrS signature\n"); + return -1; + } + if (cmdline != NULL) { if (hdr->protocol_version < 0x202) { params.cl_magic = CL_MAGIC_VALUE; diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c index f8b1f65..6fbe2fc 100644 --- a/util/cbfstool/cbfstool.c +++ b/util/cbfstool/cbfstool.c @@ -752,14 +752,19 @@ if (ret != 0) ret = parse_fv_to_payload(buffer, &output, param.compression);
- /* If it's neither ELF nor UEFI Fv, try bzImage */ + /* If it's neither ELF nor UEFI Fv, try multiboot */ + if (ret != 0) + ret = parse_multiboot_to_payload(buffer, &output, + param.compression); + + /* If it's neither ELF, UEFI Fv, nor multiboot try bzImage*/ if (ret != 0) ret = parse_bzImage_to_payload(buffer, &output, param.initrd, param.cmdline, param.compression);
/* Not a supported payload type */ if (ret != 0) { - ERROR("Not a supported payload type (ELF / FV).\n"); + ERROR("Not a supported payload type (ELF / FV / bzImage / Multiboot).\n"); buffer_delete(buffer); return -1; } diff --git a/util/cbfstool/common.h b/util/cbfstool/common.h index baefc1c..ab2e441 100644 --- a/util/cbfstool/common.h +++ b/util/cbfstool/common.h @@ -198,6 +198,8 @@ uint32_t loadaddress, uint32_t entrypoint, enum comp_algo algo); +int parse_multiboot_to_payload(const struct buffer *input, + struct buffer *output, enum comp_algo algo); /* cbfs-mkstage.c */ int parse_elf_to_stage(const struct buffer *input, struct buffer *output, enum comp_algo algo, uint32_t *location,