From c47a1a3527d988b637c1daee573cbe0170ef73c6 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 18 Jun 2017 02:21:21 +0200 Subject: [PATCH] firmware-utils: honor env SOURCE_DATE_EPOCH Use the timestamp from the enviroment SOURCE_DATE_EPOCH if set instead of the build time. Fixes reproducible builds for certain firmware images. Signed-off-by: Alexander Couzens --- tools/firmware-utils/src/addpattern.c | 20 ++++++++++++- tools/firmware-utils/src/hcsmakeimage.c | 30 +++++++++++++++++--- tools/firmware-utils/src/imagetag.c | 1 - tools/firmware-utils/src/jcgimage.c | 24 +++++++++++++++- tools/firmware-utils/src/mkrtn56uimg.c | 1 - tools/firmware-utils/src/spw303v.c | 1 - tools/firmware-utils/src/tplink-safeloader.c | 19 ++++++++++++- tools/firmware-utils/src/xorimage.c | 1 - tools/firmware-utils/src/zyxbcm.c | 1 - 9 files changed, 86 insertions(+), 12 deletions(-) diff --git a/tools/firmware-utils/src/addpattern.c b/tools/firmware-utils/src/addpattern.c index 2ecc7ffd7561..9bc486533562 100644 --- a/tools/firmware-utils/src/addpattern.c +++ b/tools/firmware-utils/src/addpattern.c @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include @@ -141,6 +142,20 @@ void usage(void) exit(EXIT_FAILURE); } +static time_t source_date_epoch = -1; +static void set_source_date_epoch() { + char *env = getenv("SOURCE_DATE_EPOCH"); + char *endptr = env; + errno = 0; + if (env && *env) { + source_date_epoch = strtoull(env, &endptr, 10); + if (errno || (endptr && *endptr != '\0')) { + fprintf(stderr, "Invalid SOURCE_DATE_EPOCH"); + exit(1); + } + } +} + struct board_info *find_board(char *id) { struct board_info *board; @@ -273,7 +288,10 @@ int main(int argc, char **argv) usage(); } - if (time(&t) == (time_t)(-1)) { + set_source_date_epoch(); + if (source_date_epoch != -1) { + t = source_date_epoch; + } else if ((time(&t) == (time_t)(-1))) { fprintf(stderr, "time call failed\n"); return EXIT_FAILURE; } diff --git a/tools/firmware-utils/src/hcsmakeimage.c b/tools/firmware-utils/src/hcsmakeimage.c index 603ea882b11b..7baa7b5845e1 100644 --- a/tools/firmware-utils/src/hcsmakeimage.c +++ b/tools/firmware-utils/src/hcsmakeimage.c @@ -5,7 +5,8 @@ #include #include #include -#include +#include +#include #include #include #include "bcmalgo.h" @@ -42,6 +43,19 @@ static void print_help ( const char* ename ) printf ( "\n" ); } +static time_t source_date_epoch = -1; +static void set_source_date_epoch() { + char *env = getenv("SOURCE_DATE_EPOCH"); + char *endptr = env; + errno = 0; + if (env && *env) { + source_date_epoch = strtoull(env, &endptr, 10); + if (errno || (endptr && *endptr != '\0')) { + fprintf(stderr, "Invalid SOURCE_DATE_EPOCH"); + exit(1); + } + } +} int main ( int argc, char** argv ) { @@ -149,11 +163,19 @@ int main ( int argc, char** argv ) { fname = filename; } - struct timeval tm; - gettimeofday ( &tm,NULL ); + + time_t t = -1; + set_source_date_epoch(); + if (source_date_epoch != -1) { + t = source_date_epoch; + } else if ((time(&t) == (time_t)(-1))) { + fprintf(stderr, "time call failed\n"); + return EXIT_FAILURE; + } + struct stat buf; stat ( input,&buf ); - ldr_header_t* head = construct_header ( magicnum, (uint16_t) majrev, (uint16_t) minrev, ( uint32_t ) tm.tv_sec, ( uint32_t ) buf.st_size, ldaddress, fname, get_file_crc ( input ) ); + ldr_header_t* head = construct_header ( magicnum, (uint16_t) majrev, (uint16_t) minrev, ( uint32_t ) t, ( uint32_t ) buf.st_size, ldaddress, fname, get_file_crc ( input ) ); free(dupe); //uint32_t magic, uint16_t rev_maj,uint16_t rev_min, uint32_t build_date, uint32_t filelen, uint32_t ldaddress, const char* filename, uint32_t crc //FILE* fd = fopen ("/tftpboot/haxorware11rev32.bin","r"); diff --git a/tools/firmware-utils/src/imagetag.c b/tools/firmware-utils/src/imagetag.c index 90fb7a4c7392..bc70399ccaa3 100644 --- a/tools/firmware-utils/src/imagetag.c +++ b/tools/firmware-utils/src/imagetag.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/tools/firmware-utils/src/jcgimage.c b/tools/firmware-utils/src/jcgimage.c index 7755eab1ed32..354c26be19b2 100644 --- a/tools/firmware-utils/src/jcgimage.c +++ b/tools/firmware-utils/src/jcgimage.c @@ -158,6 +158,20 @@ opensize(char *name, size_t *size) return fd; } +static time_t source_date_epoch = -1; +static void set_source_date_epoch() { + char *env = getenv("SOURCE_DATE_EPOCH"); + char *endptr = env; + errno = 0; + if (env && *env) { + source_date_epoch = strtoull(env, &endptr, 10); + if (errno || (endptr && *endptr != '\0')) { + fprintf(stderr, "Invalid SOURCE_DATE_EPOCH"); + exit(1); + } + } +} + /* * Write the JCG header */ @@ -167,6 +181,13 @@ mkjcgheader(struct jcg_header *h, size_t psize, char *version) uLong crc; uint16_t major = 0, minor = 0; void *payload = (void *)h + sizeof(*h); + time_t t; + + if (source_date_epoch != -1) { + t = source_date_epoch; + } else if ((time(&t) == (time_t)(-1))) { + err(1, "time call failed"); + } if (version != NULL) { if (sscanf(version, "%hu.%hu", &major, &minor) != 2) { @@ -177,7 +198,7 @@ mkjcgheader(struct jcg_header *h, size_t psize, char *version) memset(h, 0, sizeof(*h)); h->jh_magic = htonl(JH_MAGIC); h->jh_type = htonl(1); - h->jh_time = htonl(time(NULL)); + h->jh_time = htonl(t); h->jh_major = htons(major); h->jh_minor = htons(minor); @@ -303,6 +324,7 @@ main(int argc, char **argv) /* Make sure the headers have the right size */ assert(sizeof(struct jcg_header) == 512); assert(sizeof(struct uimage_header) == 64); + set_source_date_epoch(); while ((c = getopt(argc, argv, "o:k:f:u:v:h")) != -1) { switch (c) { diff --git a/tools/firmware-utils/src/mkrtn56uimg.c b/tools/firmware-utils/src/mkrtn56uimg.c index fe9ae2c87734..92aaf314a175 100644 --- a/tools/firmware-utils/src/mkrtn56uimg.c +++ b/tools/firmware-utils/src/mkrtn56uimg.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include diff --git a/tools/firmware-utils/src/spw303v.c b/tools/firmware-utils/src/spw303v.c index 654d68db2b08..684532d7e11c 100644 --- a/tools/firmware-utils/src/spw303v.c +++ b/tools/firmware-utils/src/spw303v.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include diff --git a/tools/firmware-utils/src/tplink-safeloader.c b/tools/firmware-utils/src/tplink-safeloader.c index fd4c2ab70d73..d2a1cb69ed31 100644 --- a/tools/firmware-utils/src/tplink-safeloader.c +++ b/tools/firmware-utils/src/tplink-safeloader.c @@ -709,6 +709,20 @@ static void free_image_partition(struct image_partition_entry entry) { free(entry.data); } +static time_t source_date_epoch = -1; +static void set_source_date_epoch() { + char *env = getenv("SOURCE_DATE_EPOCH"); + char *endptr = env; + errno = 0; + if (env && *env) { + source_date_epoch = strtoull(env, &endptr, 10); + if (errno || (endptr && *endptr != '\0')) { + fprintf(stderr, "Invalid SOURCE_DATE_EPOCH"); + exit(1); + } + } +} + /** Generates the partition-table partition */ static struct image_partition_entry make_partition_table(const struct flash_partition_entry *p) { struct image_partition_entry entry = alloc_image_partition("partition-table", 0x800); @@ -752,7 +766,9 @@ static struct image_partition_entry make_soft_version(uint32_t rev) { time_t t; - if (time(&t) == (time_t)(-1)) + if (source_date_epoch != -1) + t = source_date_epoch; + else if (time(&t) == (time_t)(-1)) error(1, errno, "time"); struct tm *tm = localtime(&t); @@ -1105,6 +1121,7 @@ int main(int argc, char *argv[]) { bool add_jffs2_eof = false, sysupgrade = false; unsigned rev = 0; const struct device_info *info; + set_source_date_epoch(); while (true) { int c; diff --git a/tools/firmware-utils/src/xorimage.c b/tools/firmware-utils/src/xorimage.c index b5ab83fa7a65..ca6e43742a18 100644 --- a/tools/firmware-utils/src/xorimage.c +++ b/tools/firmware-utils/src/xorimage.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include diff --git a/tools/firmware-utils/src/zyxbcm.c b/tools/firmware-utils/src/zyxbcm.c index ffeb7cc2650e..1a2926bfd31c 100644 --- a/tools/firmware-utils/src/zyxbcm.c +++ b/tools/firmware-utils/src/zyxbcm.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include -- 2.30.2