From f23a09b177d9a55679fd3a57951313b8a34dc4d9 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 23 Apr 2019 14:09:42 +0200 Subject: image-hd: add support for bootable flags on GPT Bit 2 of the GPT partition table entry "flags" attribute allows to mark the partition as bootable, so we add support for setting this flag, using the same bootable flag used for MBR partition tables. Setting this flag is useful to properly support the "Generic Distro" concept from U-Boot [1], which searches for boot scripts in the bootable partition. [1] http://git.denx.de/?p=u-boot.git;a=blob;f=doc/README.distro Signed-off-by: Thomas Petazzoni --- image-hd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/image-hd.c b/image-hd.c index 2c2860c..1f80ae7 100644 --- a/image-hd.c +++ b/image-hd.c @@ -78,6 +78,8 @@ struct gpt_partition_entry { #define GPT_SECTORS (1 + GPT_ENTRIES * sizeof(struct gpt_partition_entry) / 512) #define GPT_REVISION_1_0 0x00010000 +#define GPT_PE_FLAG_BOOTABLE (1 << 2) + static void hdimage_setup_chs(unsigned int lba, unsigned char *chs) { const unsigned int hpc = 255; @@ -275,6 +277,7 @@ static int hdimage_insert_gpt(struct image *image, struct list_head *partitions) uuid_parse(part->partition_uuid, table[i].uuid); table[i].first_lba = htole64(part->offset/512); table[i].last_lba = htole64((part->offset + part->size)/512 - 1); + table[i].flags = part->bootable ? GPT_PE_FLAG_BOOTABLE : 0; for (j = 0; j < strlen(part->name) && j < 36; j++) table[i].name[j] = htole16(part->name[j]); i++; -- cgit v1.2.3 From 1ff8c61b30dd94ee9094568c373d4ed2daceed27 Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Sat, 4 May 2019 09:11:18 +0200 Subject: hdimge: allow the last partition to fill the rest of the image Use the existing 'autoresize' partition option for this. Signed-off-by: Michael Olbrich --- README.rst | 12 ++++++--- image-hd.c | 73 ++++++++++++++++++++++++++++++++++------------------- test/hdimage.config | 3 ++- 3 files changed, 57 insertions(+), 31 deletions(-) diff --git a/README.rst b/README.rst index 67a648a..92ae9e8 100644 --- a/README.rst +++ b/README.rst @@ -89,12 +89,16 @@ Partition options: :offset: The offset of this partition as a total offset to the beginning of the device. -:size: The size of this partition in bytes. The last partition may have - size 0 to make this partition use the rest of the available space - on the device. +:size: The size of this partition in bytes. If the size and + autoresize are both not set then the size of the partition + image is used. :partition-type: Used by dos partition tables to specify the partition type. :image: The image file this partition shall be filled with -:autoresize: used by ubi (FIXME: do we need this? Isn't size = 0 enough) +:autoresize: Boolean specifying that the partition should be resized + automatically. For UBI volumes this means that the + ``autoresize`` flag is set. Only one volume can have this flag. + For hd images this can be used for the last partition. If set + the partition will fill the remaining space of the image. :bootable: Boolean specifying whether to set the bootable flag. :in-partition-table: Boolean specifying whether to include this partition in the partition table. diff --git a/image-hd.c b/image-hd.c index 1f80ae7..90f550e 100644 --- a/image-hd.c +++ b/image-hd.c @@ -404,7 +404,7 @@ static unsigned long long roundup(unsigned long long value, unsigned long long a static int hdimage_setup(struct image *image, cfg_t *cfg) { struct partition *part; - int has_extended; + int has_extended, autoresize = 0; unsigned int partition_table_entries = 0; unsigned long long now = 0; struct hdimage *hd = xzalloc(sizeof(*hd)); @@ -448,33 +448,15 @@ static int hdimage_setup(struct image *image, cfg_t *cfg) partition_table_entries = 0; list_for_each_entry(part, &image->partitions, list) { - if (part->image) { - struct image *child = image_get(part->image); - if (!child) { - image_error(image, "could not find %s\n", - part->image); - return -EINVAL; - } - if (!part->size) { - if (part->in_partition_table) - part->size = roundup(child->size, hd->align); - else - part->size = child->size; - } else if (child->size > part->size) { - image_error(image, "part %s size (%lld) too small for %s (%lld)\n", - part->name, part->size, child->file, child->size); - return -EINVAL; - } - } - if (!part->size) { - image_error(image, "part %s size must not be zero\n", - part->name); + if (autoresize) { + image_error(image, "'autoresize' is only supported " + "for the last partition\n"); return -EINVAL; } - if (part->in_partition_table && (part->size % 512)) { - image_error(image, "part %s size (%lld) must be a " - "multiple of 1 sector (512 bytes)\n", - part->name, part->size); + autoresize = part->autoresize; + if (autoresize && image->size == 0) { + image_error(image, "the images size must be specified " + "when using a 'autoresize' partition\n"); return -EINVAL; } if (hd->gpt) { @@ -538,6 +520,45 @@ static int hdimage_setup(struct image *image, cfg_t *cfg) } part->offset = roundup(now, hd->align); } + if (autoresize) { + long long partsize = image->size - now; + if (hd->gpt) + partsize -= GPT_SECTORS * 512; + if (partsize < 0) { + image_error(image, "partitions exceed device size\n"); + return -EINVAL; + } + part->size = partsize; + } + if (part->image) { + struct image *child = image_get(part->image); + if (!child) { + image_error(image, "could not find %s\n", + part->image); + return -EINVAL; + } + if (!part->size) { + if (part->in_partition_table) + part->size = roundup(child->size, hd->align); + else + part->size = child->size; + } else if (child->size > part->size) { + image_error(image, "part %s size (%lld) too small for %s (%lld)\n", + part->name, part->size, child->file, child->size); + return -EINVAL; + } + } + if (!part->size) { + image_error(image, "part %s size must not be zero\n", + part->name); + return -EINVAL; + } + if (part->in_partition_table && (part->size % 512)) { + image_error(image, "part %s size (%lld) must be a " + "multiple of 1 sector (512 bytes)\n", + part->name, part->size); + return -EINVAL; + } now = part->offset + part->size; } diff --git a/test/hdimage.config b/test/hdimage.config index 7287b6d..117e69f 100644 --- a/test/hdimage.config +++ b/test/hdimage.config @@ -68,7 +68,8 @@ image test.hdimage-2 { } partition part6 { image = "part2.img" - size = 1M + autoresize = true partition-type = 0x83 } + size = 12M } -- cgit v1.2.3 From e2f88d5af04413b61be4fce9176627ef71171677 Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Mon, 6 May 2019 08:48:24 +0200 Subject: config: allow parsing percentages Signed-off-by: Michael Olbrich --- config.c | 17 ++++++++++++++++- genimage.h | 5 ++++- util.c | 14 ++++++++++++-- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/config.c b/config.c index 3e5ab80..b0dd721 100644 --- a/config.c +++ b/config.c @@ -152,7 +152,22 @@ unsigned long long cfg_getint_suffix(cfg_t *sec, const char *name) unsigned long long val = 0; if (str) - val = strtoul_suffix(str, NULL, 0); + val = strtoul_suffix(str, NULL, NULL); + + return val; +} + +/* + * Like cfg_getint_suffix() but allow '%' as suffix as well + */ +unsigned long long cfg_getint_suffix_percent(cfg_t *sec, const char *name, + cfg_bool_t *percent) +{ + const char *str = cfg_getstr(sec, name); + unsigned long long val = 0; + + if (str) + val = strtoul_suffix(str, NULL, percent); return val; } diff --git a/genimage.h b/genimage.h index e339d1d..1e87602 100644 --- a/genimage.h +++ b/genimage.h @@ -124,7 +124,8 @@ extern struct image_handler fit_handler; (type *)( (char *)__mptr - offsetof(type,member) );}) void *xzalloc(size_t n); -unsigned long long strtoul_suffix(const char *str, char **endp, int base); +unsigned long long strtoul_suffix(const char *str, char **endp, + cfg_bool_t *percent); int init_config(void); cfg_opt_t *get_confuse_opts(void); @@ -144,6 +145,8 @@ int insert_data(struct image *image, const char *data, const char *outfile, int reload_partitions(struct image *image); unsigned long long cfg_getint_suffix(cfg_t *sec, const char *name); +unsigned long long cfg_getint_suffix_percent(cfg_t *sec, const char *name, + cfg_bool_t *percent); static inline const char *imageoutfile(const struct image *image) { diff --git a/util.c b/util.c index 2b91a94..3202b26 100644 --- a/util.c +++ b/util.c @@ -251,12 +251,16 @@ void *xzalloc(size_t n) * Like simple_strtoul() but handles an optional G, M, K or k * suffix for Gigabyte, Megabyte or Kilobyte */ -unsigned long long strtoul_suffix(const char *str, char **endp, int base) +unsigned long long strtoul_suffix(const char *str, char **endp, + cfg_bool_t *percent) { unsigned long long val; char *end; - val = strtoull(str, &end, base); + val = strtoull(str, &end, 0); + + if (percent) + *percent = cfg_false; switch (*end) { case 'G': @@ -271,6 +275,12 @@ unsigned long long strtoul_suffix(const char *str, char **endp, int base) end++; case '\0': break; + case '%': + if (percent) { + *percent = cfg_true; + break; + } + /* fall-through */ default: error("Invalid size suffix '%s' in '%s'\n", end, str); exit(1); -- cgit v1.2.3 From 393897209665117e32360d5346bc1d3960f40a41 Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Mon, 6 May 2019 08:50:05 +0200 Subject: util: add helper to calculate directory size Signed-off-by: Michael Olbrich --- genimage.h | 2 ++ util.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/genimage.h b/genimage.h index 1e87602..2559511 100644 --- a/genimage.h +++ b/genimage.h @@ -157,6 +157,8 @@ int uuid_validate(const char *str); void uuid_parse(const char *str, unsigned char *uuid); char *uuid_random(void); +unsigned long long image_dir_size(struct image *image); + uint32_t crc32(const void *data, size_t len); #endif /* __PTX_IMAGE_H */ diff --git a/util.c b/util.c index 3202b26..71104a1 100644 --- a/util.c +++ b/util.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "genimage.h" @@ -566,3 +567,52 @@ int reload_partitions(struct image *image) close(fd); return 0; } + +#define ROUND_UP(num,align) ((((num) + ((align) - 1)) & ~((align) - 1))) + +static unsigned long long dir_size(struct image *image, int dirfd, + const char *subdir, size_t blocksize) +{ + struct dirent *d; + DIR *dir; + int fd; + unsigned long long size = 0; + struct stat st; + + fd = openat(dirfd, subdir, O_RDONLY); + if (fd < 0) { + image_error(image, "failed to open '%s': %s", subdir, + strerror(errno)); + return 0; + } + + dir = fdopendir(dup(fd)); + if (dir == NULL) { + image_error(image, "failed to opendir '%s': %s", subdir, + strerror(errno)); + return 0; + } + while ((d = readdir(dir)) != NULL) { + if (d->d_type == DT_DIR) { + if (d->d_name[0] == '.' && (d->d_name[1] == '\0' || + (d->d_name[1] == '.' && d->d_name[2] == '\0'))) + continue; + size += dir_size(image, fd, d->d_name, blocksize); + continue; + } + if (d->d_type != DT_REG) + continue; + if (fstatat(fd, d->d_name, &st, AT_NO_AUTOMOUNT) < 0) { + image_error(image, "failed to stat '%s': %s", + d->d_name, strerror(errno)); + continue; + } + size += ROUND_UP(st.st_size, blocksize); + } + return size + blocksize; +} + +unsigned long long image_dir_size(struct image *image) +{ + return dir_size(image, AT_FDCWD, mountpath(image), 4096); +} -- cgit v1.2.3 From 150faf9fd298639e678c74c0ba197b2e9ad327d4 Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Tue, 7 May 2019 07:53:18 +0200 Subject: pad_file: fix copy/paste error in an error message The size of the output file is checked here, not the input file. Signed-off-by: Michael Olbrich --- util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util.c b/util.c index 2b91a94..c33906f 100644 --- a/util.c +++ b/util.c @@ -378,7 +378,7 @@ int pad_file(struct image *image, const char *infile, if (!infile) { if ((unsigned long long)s.st_size > size) { - image_error(image, "input file '%s' too large\n", outfile); + image_error(image, "output file '%s' too large\n", outfile); ret = -EINVAL; goto err_out; } -- cgit v1.2.3 From 9370489c3cd3e8587f77d4b78e8d067898315f03 Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Tue, 7 May 2019 07:51:31 +0200 Subject: util: add helper to extend images to a specified size Signed-off-by: Michael Olbrich --- genimage.h | 1 + util.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/genimage.h b/genimage.h index e339d1d..4afe3b1 100644 --- a/genimage.h +++ b/genimage.h @@ -141,6 +141,7 @@ int pad_file(struct image *image, const char *infile, size_t size, unsigned char fillpattern, enum pad_mode mode); int insert_data(struct image *image, const char *data, const char *outfile, size_t size, long offset); +int extend_file(struct image *image, size_t size); int reload_partitions(struct image *image); unsigned long long cfg_getint_suffix(cfg_t *sec, const char *name); diff --git a/util.c b/util.c index 2b91a94..e80f1b5 100644 --- a/util.c +++ b/util.c @@ -468,6 +468,49 @@ err_out: return ret; } +int extend_file(struct image *image, size_t size) +{ + const char *outfile = imageoutfile(image); + char buf = '\0'; + int f; + off_t offset; + int ret = 0; + + f = open_file(image, outfile, 0); + if (f < 0) + return f; + + offset = lseek(f, 0, SEEK_END); + if (offset < 0) { + ret = -errno; + image_error(image, "seek: %s\n", strerror(errno)); + goto out; + } + if ((size_t)offset > size) { + ret = -EINVAL; + image_error(image, "output file is larger than requested size\n"); + goto out; + } + if ((size_t)offset == size) + goto out; + + if (lseek(f, size - 1, SEEK_SET) < 0) { + ret = -errno; + image_error(image, "seek %s: %s\n", outfile, strerror(errno)); + goto out; + } + ret = write(f, &buf, 1); + if (ret < 1) { + ret = -errno; + image_error(image, "write %s: %s\n", outfile, strerror(errno)); + goto out; + } + ret = 0; +out: + close(f); + return ret; +} + int uuid_validate(const char *str) { int i; -- cgit v1.2.3 From 3af6d35b01343b9adbae51ef179fe9bc6817a7ec Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Tue, 7 May 2019 07:52:21 +0200 Subject: image-hd: add option to extend the image to the full size This can be useful when the image is used directly, e.g. with qemu. Signed-off-by: Michael Olbrich --- image-hd.c | 11 +++++++++++ test/basic-images.test | 2 +- test/hdimage.config | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/image-hd.c b/image-hd.c index 1f80ae7..2f32b8b 100644 --- a/image-hd.c +++ b/image-hd.c @@ -33,6 +33,7 @@ struct hdimage { uint32_t disksig; const char *disk_uuid; cfg_bool_t gpt; + cfg_bool_t fill; }; struct mbr_partition_entry { @@ -379,6 +380,14 @@ static int hdimage_generate(struct image *image) } } + if (hd->fill) { + ret = extend_file(image, image->size); + if (ret) { + image_error(image, "failed to fill the image.\n"); + return ret; + } + } + if (hd->partition_table) { if (hd->gpt) { ret = hdimage_insert_gpt(image, &image->partitions); @@ -414,6 +423,7 @@ static int hdimage_setup(struct image *image, cfg_t *cfg) hd->extended_partition = cfg_getint(cfg, "extended-partition"); hd->disksig = strtoul(cfg_getstr(cfg, "disk-signature"), NULL, 0); hd->gpt = cfg_getbool(cfg, "gpt"); + hd->fill = cfg_getbool(cfg, "fill"); hd->disk_uuid = cfg_getstr(cfg, "disk-uuid"); if (hd->extended_partition > 4) { @@ -564,6 +574,7 @@ cfg_opt_t hdimage_opts[] = { CFG_BOOL("partition-table", cfg_true, CFGF_NONE), CFG_INT("extended-partition", 0, CFGF_NONE), CFG_BOOL("gpt", cfg_false, CFGF_NONE), + CFG_BOOL("fill", cfg_false, CFGF_NONE), CFG_END() }; diff --git a/test/basic-images.test b/test/basic-images.test index 9b53b45..35f1bfb 100755 --- a/test/basic-images.test +++ b/test/basic-images.test @@ -193,7 +193,7 @@ exec_test_set_prereq sfdisk test_expect_success fdisk,sfdisk "hdimage" " setup_test_images && run_genimage hdimage.config test.hdimage && - check_size images/test.hdimage 9442816 && + check_size images/test.hdimage 10485760 && # check the this identifier fdisk -l images/test.hdimage | grep identifier: > hdimage.fdisk && # check partitions; filter output to handle different sfdisk versions diff --git a/test/hdimage.config b/test/hdimage.config index 7287b6d..3785432 100644 --- a/test/hdimage.config +++ b/test/hdimage.config @@ -1,6 +1,7 @@ image test.hdimage { hdimage { align = 1M + fill = true disk-signature = 0x12345678 } partition part1 { -- cgit v1.2.3 From 8d9c1a2bd3d995434f3f66c3c0a08edc035b1f3a Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Mon, 6 May 2019 08:58:42 +0200 Subject: genimage: allow percentages for image sizes Signed-off-by: Michael Olbrich --- Makefile.am | 2 ++ README.rst | 6 +++++- genimage.c | 16 +++++++++++----- genimage.h | 1 + test/basic-images.test | 5 +++++ test/ext2percent.config | 7 +++++++ test/ext2test-percent.dump | 40 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 test/ext2percent.config create mode 100644 test/ext2test-percent.dump diff --git a/Makefile.am b/Makefile.am index 3c96229..d283212 100644 --- a/Makefile.am +++ b/Makefile.am @@ -51,6 +51,8 @@ EXTRA_DIST += \ test/cramfs.config \ test/ext2.config \ test/ext2test.dump \ + test/ext2percent.config \ + test/ext2test-percent.dump \ test/ext3.config \ test/ext3test.dump \ test/ext4.config \ diff --git a/README.rst b/README.rst index 67a648a..6cc5846 100644 --- a/README.rst +++ b/README.rst @@ -68,7 +68,11 @@ Here are all options for images: :name: The name of this image. This is used for some image types to set the name of the image. -:size: Size of this image in bytes +:size: Size of this image in bytes. 'k', 'M' or 'G' can be used as suffix to + specify the size in multiple of 1024 etc. If the image if filled from + a mountpoint then '%' as suffix indicates a percentage. '200%' means + the resulting filesystem should be about 50% filled. Note that is is + only a rough estimate based on the original size of the content. :mountpoint: mountpoint if image refers to a filesystem image. The default is "/". The content of "${rootpath}${mountpoint}" will be used used fill the filesystem. diff --git a/genimage.c b/genimage.c index 64a7b2e..ca2c6d6 100644 --- a/genimage.c +++ b/genimage.c @@ -157,6 +157,11 @@ static int image_setup(struct image *image) image->seen = -1; + if (image->size_is_percent) { + image->size = image_dir_size(image) * image->size / 100; + image->size_is_percent = cfg_false; + } + list_for_each_entry(part, &image->partitions, list) { struct image *child; if (!part->image) @@ -664,7 +669,8 @@ int main(int argc, char *argv[]) list_add_tail(&image->list, &images); image->file = cfg_title(imagesec); image->name = cfg_getstr(imagesec, "name"); - image->size = cfg_getint_suffix(imagesec, "size"); + image->size = cfg_getint_suffix_percent(imagesec, "size", + &image->size_is_percent); image->mountpoint = cfg_getstr(imagesec, "mountpoint"); image->exec_pre = cfg_getstr(imagesec, "exec-pre"); image->exec_post = cfg_getstr(imagesec, "exec-post"); @@ -717,6 +723,10 @@ int main(int argc, char *argv[]) if (ret) goto cleanup; + ret = collect_mountpoints(); + if (ret) + goto cleanup; + list_for_each_entry(image, &images, list) { ret = image_setup(image); if (ret) @@ -731,10 +741,6 @@ int main(int argc, char *argv[]) if (ret) goto cleanup; - ret = collect_mountpoints(); - if (ret) - goto cleanup; - list_for_each_entry(image, &images, list) { ret = setenv_image(image); if (ret) diff --git a/genimage.h b/genimage.h index 2559511..1ebe1cd 100644 --- a/genimage.h +++ b/genimage.h @@ -51,6 +51,7 @@ struct image { const char *name; const char *file; unsigned long long size; + cfg_bool_t size_is_percent; const char *mountpoint; const char *exec_pre; const char *exec_post; diff --git a/test/basic-images.test b/test/basic-images.test index 9b53b45..cf6d68b 100755 --- a/test/basic-images.test +++ b/test/basic-images.test @@ -157,6 +157,11 @@ test_expect_success genext2fs,e2fsck "ext2" " check_ext images/test.ext2 ext2test 4194304 " +test_expect_success genext2fs,e2fsck "ext2percent" " + run_genimage ext2percent.config test.ext2 && + check_ext images/test.ext2 ext2test-percent 69632 +" + test_expect_success genext2fs,e2fsck "ext3" " run_genimage ext3.config test.ext3 && check_ext images/test.ext3 ext3test 4194304 diff --git a/test/ext2percent.config b/test/ext2percent.config new file mode 100644 index 0000000..f9cd848 --- /dev/null +++ b/test/ext2percent.config @@ -0,0 +1,7 @@ +image test.ext2 { + ext2 { + label = "ext2test" + fs-timestamp = "20000101000000" + } + size = 100% +} diff --git a/test/ext2test-percent.dump b/test/ext2test-percent.dump new file mode 100644 index 0000000..f771eb4 --- /dev/null +++ b/test/ext2test-percent.dump @@ -0,0 +1,40 @@ +Filesystem volume name: ext2test +Last mounted on: +Filesystem magic number: 0xEF53 +Filesystem revision #: 0 (original) +Filesystem features: (none) +Default mount options: (none) +Filesystem state: clean +Errors behavior: Unknown (continue) +Filesystem OS type: Linux +Inode count: 56 +Block count: 68 +Reserved block count: 3 +Free blocks: 36 +Free inodes: 5 +First block: 1 +Block size: 1024 +Fragment size: 1024 +Blocks per group: 72 +Fragments per group: 72 +Inodes per group: 56 +Inode blocks per group: 7 +Filesystem created: Sat Jan 1 00:00:00 2000 +Last mount time: n/a +Last write time: Sat Jan 1 00:00:00 2000 +Mount count: 0 +Maximum mount count: 20 +Last checked: Sat Jan 1 00:00:00 2000 +Check interval: 0 () +Reserved blocks uid: 0 (user root) +Reserved blocks gid: 0 (group root) + + +Group 0: (Blocks 1-67) + Primary superblock at 1, Group descriptors at 2-2 + Block bitmap at 3 (+2) + Inode bitmap at 4 (+3) + Inode table at 5-11 (+4) + 36 free blocks, 5 free inodes, 18 directories + Free blocks: 32-67 + Free inodes: 52-56 -- cgit v1.2.3 From 34aa92e4faf52c1a14c7c772c5b980e4bdc40b48 Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Tue, 7 May 2019 12:45:02 +0200 Subject: travis: find any logfile and dump it Signed-off-by: Michael Olbrich --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 395937e..187a7f5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,4 +23,4 @@ script: - ./configure - make distcheck after_failure: - - cat genimage-*/_build/test-suite.log + - find -name test-suite.log -print0 | xargs -0 cat -- cgit v1.2.3 From 089e90c800ba8fabfa4440736b4fd6afc32903c8 Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Sun, 19 May 2019 11:58:11 +0200 Subject: release version 11 Signed-off-by: Michael Olbrich --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 563b969..95e902d 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ(2.60) AC_INIT([genimage], - [10], + [11], [oss-tools@pengutronix.de], [genimage], [http://www.pengutronix.de/genimage/]) -- cgit v1.2.3 From 05e7677b9197d3f5ccd1f97b2115b03a0d9b4f89 Mon Sep 17 00:00:00 2001 From: Bastian Krause Date: Thu, 6 Jun 2019 12:08:06 +0200 Subject: image-rauc: support PKCS#11 URLs for cert/key RAUC supports PKCS#11 URLs instead of filenames for the --cert and --key arguments: https://rauc.readthedocs.io/en/latest/advanced.html#pkcs-11-support So do not add cert and key as image partitions if the "pkcs11" prefix is detected. Signed-off-by: Bastian Krause --- image-rauc.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/image-rauc.c b/image-rauc.c index 79aab10..c4195a3 100644 --- a/image-rauc.c +++ b/image-rauc.c @@ -91,29 +91,36 @@ static int rauc_generate(struct image *image) static int rauc_parse(struct image *image, cfg_t *cfg) { + const char *pkcs11_prefix = "pkcs11:"; unsigned int i; unsigned int num_files; struct partition *part; + char *part_image_key; + char *part_image_cert; - part = xzalloc(sizeof *part); - part->image = cfg_getstr(image->imagesec, "key"); - if (!part->image) { + part_image_key = cfg_getstr(image->imagesec, "key"); + if (!part_image_key) { image_error(image, "Mandatory 'key' option is missing!\n"); - free(part); return -EINVAL; } - part->partition_type = RAUC_KEY; - list_add_tail(&part->list, &image->partitions); + if (strncmp(pkcs11_prefix, part_image_key, strlen(pkcs11_prefix))) { + part = xzalloc(sizeof *part); + part->image = part_image_key; + part->partition_type = RAUC_KEY; + list_add_tail(&part->list, &image->partitions); + } - part = xzalloc(sizeof *part); - part->image = cfg_getstr(image->imagesec, "cert"); - if (!part->image) { + part_image_cert = cfg_getstr(image->imagesec, "cert"); + if (!part_image_cert) { image_error(image, "Mandatory 'cert' option is missing!\n"); - free(part); return -EINVAL; } - part->partition_type = RAUC_CERT; - list_add_tail(&part->list, &image->partitions); + if (strncmp(pkcs11_prefix, part_image_cert, strlen(pkcs11_prefix))) { + part = xzalloc(sizeof *part); + part->image = part_image_cert; + part->partition_type = RAUC_CERT; + list_add_tail(&part->list, &image->partitions); + } num_files = cfg_size(cfg, "file"); for (i = 0; i < num_files; i++) { -- cgit v1.2.3 From dd20bcfd78ffb2c6bb5ceed6a474cb2830d240c0 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Wed, 26 Jun 2019 09:38:35 +0200 Subject: hdimage: use random mbr disk signature if not provided Disk signature is part of PARTUUID for MBR partitions. PARTUUID can be used to provide root partition, instead of hardcoding /dev/sd* or /dev/mmcblk* nodes. The advantage of using PARTUUID is that it doesn't change across reboots (depending on device drivers probe order). Add a possibility to use random value as disk signature, which will be used after specifying 'disk-signature = random'. Using it will make it less likely to have multiple SD cards with the same PARTUUIDs connected to a single system, resulting in PARTUUID conflict. Signed-off-by: Marcin Niestroj --- image-hd.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/image-hd.c b/image-hd.c index 204d601..93f29e2 100644 --- a/image-hd.c +++ b/image-hd.c @@ -416,12 +416,13 @@ static int hdimage_setup(struct image *image, cfg_t *cfg) int has_extended, autoresize = 0; unsigned int partition_table_entries = 0; unsigned long long now = 0; + const char *disk_signature; struct hdimage *hd = xzalloc(sizeof(*hd)); hd->align = cfg_getint_suffix(cfg, "align"); hd->partition_table = cfg_getbool(cfg, "partition-table"); hd->extended_partition = cfg_getint(cfg, "extended-partition"); - hd->disksig = strtoul(cfg_getstr(cfg, "disk-signature"), NULL, 0); + disk_signature = cfg_getstr(cfg, "disk-signature"); hd->gpt = cfg_getbool(cfg, "gpt"); hd->fill = cfg_getbool(cfg, "fill"); hd->disk_uuid = cfg_getstr(cfg, "disk-uuid"); @@ -456,6 +457,11 @@ static int hdimage_setup(struct image *image, cfg_t *cfg) hd->disk_uuid = uuid_random(); } + if (!strcmp(disk_signature, "random")) + hd->disksig = random(); + else + hd->disksig = strtoul(disk_signature, NULL, 0); + partition_table_entries = 0; list_for_each_entry(part, &image->partitions, list) { if (autoresize) { -- cgit v1.2.3 From 909c449011db54ef13d997833e5b7921ba0e7f56 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Mon, 5 Aug 2019 21:09:25 +0200 Subject: README: describe random disk-signature option It is now possible to use random disk signature by specifying 'disk-signature = random'. Signed-off-by: Marcin Niestroj --- README.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index e7c14e4..eac10ef 100644 --- a/README.rst +++ b/README.rst @@ -189,7 +189,9 @@ Options: :extended-partition: Number of the extended partition. Contains the number of the extended partition between 1 and 4 or 0 for automatic. Defaults to 0. -:disk-signature: 32 bit integer used as disk signature (offset 440 in the MBR) +:disk-signature: 32 bit integer used as disk signature (offset 440 in the + MBR). Using a special value ``random`` will result in + using random 32 bit number. :gpt: Boolean. If true, a GPT type partion table is written. If false a DOS type partition table is written. Defaults to false. :disk-uuid: UUID string used as disk id in GPT partitioning. Defaults to a -- cgit v1.2.3 From f2b104aa68a0dff3f0bf6b481f9724722cb01939 Mon Sep 17 00:00:00 2001 From: George Hilliard Date: Wed, 7 Aug 2019 00:35:20 -0500 Subject: Prefix mountpoints with mp- to avoid conflict with "root" Specifying an image with mountpoint "/root" would cause the mountpoint's location to be "root", which conflicts with the location for the actual filesystem root. Fix this by appending a prefix. Closes #67 on GitHub. Signed-off-by: George Hilliard --- genimage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/genimage.c b/genimage.c index ca2c6d6..aafd3b7 100644 --- a/genimage.c +++ b/genimage.c @@ -392,7 +392,7 @@ static struct mountpoint *add_mountpoint(const char *path) path_sanitized = sanitize_path(path); mp = xzalloc(sizeof(*mp)); mp->path = strdup(path); - xasprintf(&mp->mountpath, "%s/%s", tmppath(), path_sanitized); + xasprintf(&mp->mountpath, "%s/mp-%s", tmppath(), path_sanitized); list_add_tail(&mp->list, &mountpoints); free(path_sanitized); -- cgit v1.2.3 From c0e7f24642f625aa3d4410cefe10e2f456164f15 Mon Sep 17 00:00:00 2001 From: George Hilliard Date: Wed, 11 Sep 2019 14:30:16 -0500 Subject: hdimage: Implement 'gpt-location' option to move GPT table This allows the user to specify the location of the GPT table. This is useful if a device requires that the bootloader be located in a location that conflicts with the normal location of the GPT table. Also, this changes the calculation of the "first usable LBA" to be the first *listed* partition; this allows the calculation to disregard the non-listed bootloaders that make this feature useful. It is up to the user to ensure that the GPT table is in a location that does not conflict with any non-listed partition entries. Signed-off-by: George Hilliard --- README.rst | 5 +++++ image-hd.c | 17 ++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index eac10ef..2f62e85 100644 --- a/README.rst +++ b/README.rst @@ -194,6 +194,11 @@ Options: using random 32 bit number. :gpt: Boolean. If true, a GPT type partion table is written. If false a DOS type partition table is written. Defaults to false. +:gpt-location: Location of the GPT table. Occasionally useful for moving the GPT + table away from where a bootloader is placed due to hardware + requirements. All partitions in the table must begin after this + table. Regardless of this setting, the GPT header will still be + placed at 512 bytes (sector 1). Defaults to 1024 bytes (sector 2). :disk-uuid: UUID string used as disk id in GPT partitioning. Defaults to a random value. diff --git a/image-hd.c b/image-hd.c index 93f29e2..9764529 100644 --- a/image-hd.c +++ b/image-hd.c @@ -33,6 +33,7 @@ struct hdimage { uint32_t disksig; const char *disk_uuid; cfg_bool_t gpt; + unsigned long long gpt_location; cfg_bool_t fill; }; @@ -261,14 +262,14 @@ static int hdimage_insert_gpt(struct image *image, struct list_head *partitions) header.backup_lba = htole64(image->size/512 - 1); header.last_usable_lba = htole64(image->size/512 - 1 - GPT_SECTORS); uuid_parse(hd->disk_uuid, header.disk_uuid); - header.starting_lba = htole64(2); + header.starting_lba = htole64(hd->gpt_location/512); header.number_entries = htole32(GPT_ENTRIES); header.entry_size = htole32(sizeof(struct gpt_partition_entry)); i = 0; memset(&table, 0, sizeof(table)); list_for_each_entry(part, partitions, list) { - if (header.first_usable_lba == 0) + if (header.first_usable_lba == 0 && part->in_partition_table) header.first_usable_lba = htole64(part->offset / 512); if (!part->in_partition_table) @@ -291,7 +292,7 @@ static int hdimage_insert_gpt(struct image *image, struct list_head *partitions) image_error(image, "failed to write GPT\n"); return ret; } - ret = insert_data(image, (char *)&table, outfile, sizeof(table), 2*512); + ret = insert_data(image, (char *)&table, outfile, sizeof(table), hd->gpt_location); if (ret) { image_error(image, "failed to write GPT table\n"); return ret; @@ -424,6 +425,7 @@ static int hdimage_setup(struct image *image, cfg_t *cfg) hd->extended_partition = cfg_getint(cfg, "extended-partition"); disk_signature = cfg_getstr(cfg, "disk-signature"); hd->gpt = cfg_getbool(cfg, "gpt"); + hd->gpt_location = cfg_getint_suffix(cfg, "gpt-location"); hd->fill = cfg_getbool(cfg, "fill"); hd->disk_uuid = cfg_getstr(cfg, "disk-uuid"); @@ -462,6 +464,14 @@ static int hdimage_setup(struct image *image, cfg_t *cfg) else hd->disksig = strtoul(disk_signature, NULL, 0); + if (hd->gpt_location == 0) { + hd->gpt_location = 2*512; + } + else if (hd->gpt_location % 512) { + image_error(image, "GPT table location (%lld) must be a " + "multiple of 1 sector (512 bytes)", hd->gpt_location); + } + partition_table_entries = 0; list_for_each_entry(part, &image->partitions, list) { if (autoresize) { @@ -601,6 +611,7 @@ cfg_opt_t hdimage_opts[] = { CFG_BOOL("partition-table", cfg_true, CFGF_NONE), CFG_INT("extended-partition", 0, CFGF_NONE), CFG_BOOL("gpt", cfg_false, CFGF_NONE), + CFG_STR("gpt-location", NULL, CFGF_NONE), CFG_BOOL("fill", cfg_false, CFGF_NONE), CFG_END() }; -- cgit v1.2.3 From d5ab008b35dc691c22b8b643a96b8d178a0328e3 Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Fri, 20 Sep 2019 19:17:34 +0200 Subject: image-hd: the secondary GPT header should point to the secondary GPT table Signed-off-by: Michael Olbrich --- image-hd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/image-hd.c b/image-hd.c index 9764529..fcb05d3 100644 --- a/image-hd.c +++ b/image-hd.c @@ -308,6 +308,7 @@ static int hdimage_insert_gpt(struct image *image, struct list_head *partitions) header.header_crc = 0; header.current_lba = htole64(image->size/512 - 1); header.backup_lba = htole64(1); + header.starting_lba = htole64(image->size/512 - GPT_SECTORS); header.header_crc = htole32(crc32(&header, sizeof(header))); ret = insert_data(image, (char *)&table, outfile, sizeof(table), image->size - GPT_SECTORS*512); -- cgit v1.2.3 From c33962e0de664bb977d234f7b31ebd00823b139d Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Fri, 20 Sep 2019 19:17:54 +0200 Subject: test: check hd images with 'sfdisk -V' It will complain about a corrupt secondary GPT table. Unfortunately, the return value remains zero, so we need to check the output. Ignore messages about unused empty space at the end of the device. Signed-off-by: Michael Olbrich --- test/basic-images.test | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/basic-images.test b/test/basic-images.test index 4554b7a..52e2f22 100755 --- a/test/basic-images.test +++ b/test/basic-images.test @@ -89,6 +89,14 @@ check_size() { fi } +sfdisk_validate() { + if [ -n "$(sfdisk -q -V "${1}" 2>&1 | grep -v unallocated)" ]; then + echo "'sfdisk -V' failed with:" + sfdisk -V "${1}" 2>&1 + return 1 + fi +} + exec_test_set_prereq() { command -v "${1}" > /dev/null && test_set_prereq "${1/./_}" } @@ -199,6 +207,7 @@ test_expect_success fdisk,sfdisk "hdimage" " setup_test_images && run_genimage hdimage.config test.hdimage && check_size images/test.hdimage 10485760 && + sfdisk_validate images/test.hdimage && # check the this identifier fdisk -l images/test.hdimage | grep identifier: > hdimage.fdisk && # check partitions; filter output to handle different sfdisk versions @@ -225,6 +234,7 @@ test_expect_success fdisk-gpt,sfdisk-gpt "hdimage4" " setup_test_images && run_genimage hdimage4.config test.hdimage && check_size images/test.hdimage 7356928 && + sfdisk_validate images/test.hdimage && # check the this identifier fdisk -l images/test.hdimage | grep identifier: > hdimage4.fdisk && # check partitions; filter output to handle different sfdisk versions -- cgit v1.2.3