Alexandru Gagniuc (mr.nuke.me@gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/4810
-gerrit
commit bfb6f0f224ab2f8dd91c20c3e636692a044c59e2 Author: Alexandru Gagniuc mr.nuke.me@gmail.com Date: Fri Jan 24 19:49:07 2014 -0600
YOU SHALL NOT MERGE!
, _,- (\ _,-',' \ ,-" ,' \ ,' ,' \ _:.----__.-."-._,-._ \ .-".:--`:::::.:.:' ) `-. \ `. ::L .::::::'`-._ ( ) : \ ":::::::' `-. `-_ ) ,' \.._/_`:::,' `. . `-: :" _ """ `-_ . ` `. "\"":--\ `-.__ ` . `. \':: \ _-"__`--.__ ` . `. _,--..- \ :: _-":)( ""-._ ` `.-'' \`:`-":::/ \ . . `-. : :\:::::::' \ ` . `. : :\:':':' . \ `, : : : \ . \ . `. : ,- __`:\ . \ . ` ,' ,: : ,-' _,---"" : \ ' \ . :-" ,' ,-"" : \: . : \ ` ' ,' / ' : : \ . \ . _,' ,-' : . ' : :` `,-' ,--' : : : ,'-._,' ,-' _: : :8: ,--' :dd`-._,'-._.__-""' ,' ,----' _.----' __..--"" ""
cbfstool: add preliminary partitioning suport
Based on Proposal 2 of my user page
Change-Id: I6770a9f8a459b4f204f5a75b98897a502af3ac66 Signed-off-by: Alexandru Gagniuc mr.nuke.me@gmail.com --- util/cbfstool/Makefile.inc | 1 + util/cbfstool/cbfs.h | 15 ++++++++++- util/cbfstool/cbfs_image.c | 36 +++++++++++++++++++++++++++ util/cbfstool/cbfs_image.h | 2 ++ util/cbfstool/cbfs_partition.c | 56 ++++++++++++++++++++++++++++++++++++++++++ util/cbfstool/cbfs_partition.h | 20 +++++++++++++++ util/cbfstool/cbfstool.c | 2 ++ 7 files changed, 131 insertions(+), 1 deletion(-)
diff --git a/util/cbfstool/Makefile.inc b/util/cbfstool/Makefile.inc index fc120f3..c5d284c 100644 --- a/util/cbfstool/Makefile.inc +++ b/util/cbfstool/Makefile.inc @@ -3,6 +3,7 @@ cbfsobj += cbfstool.o cbfsobj += common.o cbfsobj += compress.o cbfsobj += cbfs_image.o +cbfsobj += cbfs_partition.o cbfsobj += cbfs-mkstage.o cbfsobj += cbfs-mkpayload.o cbfsobj += fit.o diff --git a/util/cbfstool/cbfs.h b/util/cbfstool/cbfs.h index 35d0670..423e903 100644 --- a/util/cbfstool/cbfs.h +++ b/util/cbfstool/cbfs.h @@ -35,13 +35,26 @@ struct cbfs_header { uint32_t align; uint32_t offset; uint32_t architecture; /* Version 2 */ - uint32_t pad[1]; + uint32_t ptable_offset; } __attribute__ ((packed));
#define CBFS_ARCHITECTURE_UNKNOWN 0xFFFFFFFF #define CBFS_ARCHITECTURE_X86 0x00000001 #define CBFS_ARCHITECTURE_ARMV7 0x00000010
+#define CBFS_PARTITION_MAGIC 0x43425054 /* "CBPT" in ASCII */ +#define CBFS_PARTITION_NAME_LEN 32 +#define CBFS_PARTITION_ENTRY_LEN 0x30 +#define CBFS_PARTITION_ENTRY_ALIGN 0x10 + +struct cbfs_partition { + uint32_t magic; + uint32_t offset; + uint32_t size; + uint32_t flags; + char name[32]; +}; /* Don't fucking pack this. If you need this packed, you have a bug */ + #define CBFS_FILE_MAGIC "LARCHIVE"
struct cbfs_file { diff --git a/util/cbfstool/cbfs_image.c b/util/cbfstool/cbfs_image.c index 401654e..66cf32f 100644 --- a/util/cbfstool/cbfs_image.c +++ b/util/cbfstool/cbfs_image.c @@ -25,6 +25,7 @@
#include "common.h" #include "cbfs_image.h" +#include "cbfs_partition.h"
/* The file name align is not defined in CBFS spec -- only a preference by * (old) cbfstool. */ @@ -145,10 +146,12 @@ int cbfs_image_create(struct cbfs_image *image, struct buffer *bootblock, int32_t bootblock_offset, int32_t header_offset, + int32_t ptable_offset, int32_t entries_offset) { struct cbfs_header *header; struct cbfs_file *entry; + struct cbfs_partition part; uint32_t cbfs_len; size_t entry_header_len;
@@ -159,6 +162,8 @@ int cbfs_image_create(struct cbfs_image *image,
if (buffer_create(&image->buffer, size, "(new)") != 0) return -1; + if ((image->ptable = malloc(sizeof(part) * 11)) == NULL) + return -1; image->header = NULL; memset(image->buffer.data, CBFS_CONTENT_DEFAULT_VALUE, size);
@@ -229,6 +234,33 @@ int cbfs_image_create(struct cbfs_image *image, if (header_offset > entries_offset && header_offset < cbfs_len) cbfs_len = header_offset; cbfs_len -= entries_offset + align + entry_header_len; + + /* + * Now find space for the partition table. + * Pre-allocate 10 entries for now. This should be sufficient for most + * use-cases, and makes sure we don't have to reduce the final entry. + * FIXME: Only works for bootblock on top. We really should listen to + * the wisdom of the caller and put this where requested. + */ + ptable_offset = header_offset - cbfs_ptable_calc_size(10); + /* Align down */ + ptable_offset &= ~(CBFS_PARTITION_ENTRY_ALIGN - 1); + cbfs_len -= (bootblock_offset - ptable_offset); + if (IS_TOP_ALIGNED_ADDRESS(header_offset)) + header_offset += (int32_t) size; + header->ptable_offset = ntohl(ptable_offset); + + LOG("pizdatable offset 0x%x\n", ptable_offset); + + /* No, don't use ntohl shit here */ + cbfs_partition_entry_init(&image->ptable[0], + "coreboot", entries_offset, cbfs_len, 0); + /* Terminate ptable list */ + image->ptable[1].magic = 0xFFFFFFFF; + + cbfs_ptable_serialize(image->buffer.data + ptable_offset, + image->ptable); + cbfs_create_empty_entry(image, entry, cbfs_len, ""); LOG("Created CBFS image (capacity = %d bytes)\n", cbfs_len); return 0; @@ -247,6 +279,7 @@ int cbfs_image_from_file(struct cbfs_image *image, const char *filename) cbfs_image_delete(image); return -1; } + image->ptable = NULL; cbfs_fix_legacy_size(image);
return 0; @@ -261,7 +294,10 @@ int cbfs_image_write_file(struct cbfs_image *image, const char *filename) int cbfs_image_delete(struct cbfs_image *image) { buffer_delete(&image->buffer); + if (image->ptable) + free(image->ptable); image->header = NULL; + image->ptable = NULL; return 0; }
diff --git a/util/cbfstool/cbfs_image.h b/util/cbfstool/cbfs_image.h index 7ad418a..847ee5d 100644 --- a/util/cbfstool/cbfs_image.h +++ b/util/cbfstool/cbfs_image.h @@ -29,6 +29,7 @@ struct cbfs_image { struct buffer buffer; struct cbfs_header *header; + struct cbfs_partition *ptable; };
/* Creates an empty CBFS image by given size, and description to its content @@ -43,6 +44,7 @@ int cbfs_image_create(struct cbfs_image *image, struct buffer *bootblock, int32_t bootblock_offset, int32_t header_offset, + int32_t ptable_offset, int32_t entries_offset);
/* Loads a CBFS image from file. Returns 0 on success, otherwise non-zero. */ diff --git a/util/cbfstool/cbfs_partition.c b/util/cbfstool/cbfs_partition.c new file mode 100644 index 0000000..9315c94 --- /dev/null +++ b/util/cbfstool/cbfs_partition.c @@ -0,0 +1,56 @@ +/* + * Manipulators for CBFS partitions + * + * Copyright (C) 2014 Alexandru Gagniuc mr.nuke.me@gmail.com + * Subject to the GNU GPL v2, or (at your option) any later version. + */ + +#include "cbfs_partition.h" +#include "endian_stream.h" +#include "../../payloads/external/GRUB2/grub2/grub-core/lib/libgcrypt-grub/src/types.h" + +#include <string.h> + +size_t cbfs_ptable_calc_size(size_t num_entries) +{ + /* The last 4 bytes are the table terminator */ + return CBFS_PARTITION_ENTRY_LEN * num_entries + 4; +} + +void cbfs_partition_entry_init(struct cbfs_partition *part, const char *name, + uint32_t offset, uint32_t size, uint32_t fags) +{ + part->magic = CBFS_PARTITION_MAGIC; + part->offset = offset; + part->size = size; + part->flags = fags; + strncpy(part->name, name, CBFS_PARTITION_NAME_LEN); +} + +void cbfs_partition_serialize(void *dest, const struct cbfs_partition *part) +{ + h_to_be32(part->magic, dest + 0); + h_to_be32(part->offset, dest + 4); + h_to_be32(part->size, dest + 8); + h_to_be32(part->flags, dest + 12); + memset(dest, 0xff, CBFS_PARTITION_NAME_LEN); + strncpy(dest + 16, part->name, CBFS_PARTITION_NAME_LEN); +} + +void cbfs_partition_deserialize(struct cbfs_partition *part, const void *src) +{ + part->magic = be32_to_h(src + 0); + part->offset = be32_to_h(src + 4); + part->size = be32_to_h(src + 8); + part->flags = be32_to_h(src + 12); + strncpy(part->name, src + 16, CBFS_PARTITION_NAME_LEN); +} + +void cbfs_ptable_serialize(void *dest, const struct cbfs_partition *part) +{ + while (part->magic == CBFS_PARTITION_MAGIC) { + cbfs_partition_serialize(dest, part); + part++; + dest += 16; + } +} diff --git a/util/cbfstool/cbfs_partition.h b/util/cbfstool/cbfs_partition.h new file mode 100644 index 0000000..b6d6cf4 --- /dev/null +++ b/util/cbfstool/cbfs_partition.h @@ -0,0 +1,20 @@ +/* + * Prototypes for manipulating for CBFS partitions + * + * Copyright (C) 2014 Alexandru Gagniuc mr.nuke.me@gmail.com + * Subject to the GNU GPL v2, or (at your option) any later version. + */ + +#ifndef __CBFS_PARTITION_H +#define __CBFS_PARTITION_H + +#include "cbfs.h" +#include <stddef.h> + +void cbfs_partition_entry_init(struct cbfs_partition *part, const char *name, + uint32_t offset, uint32_t size, uint32_t flags); +void cbfs_partition_serialize(void *dest, const struct cbfs_partition *part); +void cbfs_partition_deserialize(struct cbfs_partition *part, const void *src); +size_t cbfs_ptable_calc_size(size_t num_entries); +void cbfs_ptable_serialize(void *dest, const struct cbfs_partition *part); +#endif /* __CBFS_PARTITION_H */ diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c index 34002a9..0040a98 100644 --- a/util/cbfstool/cbfstool.c +++ b/util/cbfstool/cbfstool.c @@ -55,6 +55,7 @@ static struct param { uint32_t pagesize; uint32_t offset; uint32_t top_aligned; + uint32_t ptable_offset; int fit_empty_entries; comp_algo algo; /* for linux payloads */ @@ -373,6 +374,7 @@ static int cbfs_create(void) &bootblock, param.baseaddress, param.headeroffset, + param.ptable_offset, param.offset) != 0) { ERROR("Failed to create %s.\n", param.cbfs_name); return 1;