aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/time.pl
blob: a23b57c89e3c8cd16960b5d3874f68a20c72b49c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#!/usr/bin/env perl

use strict;
use warnings;
use Config;

if (@ARGV < 2) {
	die "Usage: $0 <prefix> <command...>\n";
}

sub gettime {
	my ($sec, $usec);

	eval {
		require Time::HiRes;
		($sec, $usec) = Time::HiRes::gettimeofday();
	};

	unless (defined($sec) && defined($usec)) {
		my $tv_t = ($Config{'longsize'} == 8) ? 'qq' : 'll';
		my $tv = pack $tv_t, 0, 0;

		eval {
			require 'syscall.ph';
			syscall(SYS_gettimeofday(), $tv, 0);
		};

		($sec, $usec) = unpack $tv_t, $tv;
	}

	return ($sec, $usec);
}

my ($prefix, @cmd) = @ARGV;
my ($sec, $usec) = gettime();
my $pid = fork();

if (!defined($pid)) {
	die "$0: Failure to fork(): $!\n";
}
elsif ($pid == 0) {
	exec(@cmd);
	die "$0: Failure to exec(): $!\n";
}
else {
	$SIG{'INT'} = 'IGNORE';
	$SIG{'QUIT'} = 'IGNORE';

	if (waitpid($pid, 0) == -1) {
		die "$0: Failure to waitpid(): $!\n";
	}

	my $exitcode = $? >> 8;
	my ($sec2, $usec2) = gettime();
	my (undef, undef, $cuser, $csystem) = times();

	printf STDERR "%s#%.2f#%.2f#%.2f\n",
		$prefix, $cuser, $csystem,
		($sec2 - $sec) + ($usec2 - $usec) / 1000000;

	$SIG{'INT'} = 'DEFAULT';
	$SIG{'QUIT'} = 'DEFAULT';

	exit $exitcode;
}
n char *progname; extern uint32_t kernel_len; extern struct file_info kernel_info; extern struct file_info rootfs_info; extern struct flash_layout *layout; extern uint32_t rootfs_ofs; extern uint32_t rootfs_align; extern int combined; extern int strip_padding; extern int add_jffs2_eof; static unsigned char jffs2_eof_mark[4] = {0xde, 0xad, 0xc0, 0xde}; void fill_header(char *buf, int len); struct flash_layout *find_layout(struct flash_layout *layouts, const char *id) { struct flash_layout *ret; struct flash_layout *l; ret = NULL; for (l = layouts; l->id != NULL; l++){ if (strcasecmp(id, l->id) == 0) { ret = l; break; } }; return ret; } void get_md5(const char *data, int size, uint8_t *md5) { MD5_CTX ctx; MD5_Init(&ctx); MD5_Update(&ctx, data, size); MD5_Final(md5, &ctx); } int get_file_stat(struct file_info *fdata) { struct stat st; int res; if (fdata->file_name == NULL) return 0; res = stat(fdata->file_name, &st); if (res){ ERRS("stat failed on %s", fdata->file_name); return res; } fdata->file_size = st.st_size; return 0; } int read_to_buf(const struct file_info *fdata, char *buf) { FILE *f; int ret = EXIT_FAILURE; f = fopen(fdata->file_name, "r"); if (f == NULL) { ERRS("could not open \"%s\" for reading", fdata->file_name); goto out; } errno = 0; fread(buf, fdata->file_size, 1, f); if (errno != 0) { ERRS("unable to read from file \"%s\"", fdata->file_name); goto out_close; } ret = EXIT_SUCCESS; out_close: fclose(f); out: return ret; } static int pad_jffs2(char *buf, int currlen, int maxlen) { int len; uint32_t pad_mask; len = currlen; pad_mask = (4 * 1024) | (64 * 1024); /* EOF at 4KB and at 64KB */ while ((len < maxlen) && (pad_mask != 0)) { uint32_t mask; int i; for (i = 10; i < 32; i++) { mask = 1 << i; if (pad_mask & mask) break; } len = ALIGN(len, mask); for (i = 10; i < 32; i++) { mask = 1 << i; if ((len & (mask - 1)) == 0) pad_mask &= ~mask; } for (i = 0; i < sizeof(jffs2_eof_mark); i++) buf[len + i] = jffs2_eof_mark[i]; len += sizeof(jffs2_eof_mark); } return len; } int write_fw(const char *ofname, const char *data, int len) { FILE *f; int ret = EXIT_FAILURE; f = fopen(ofname, "w"); if (f == NULL) { ERRS("could not open \"%s\" for writing", ofname); goto out; } errno = 0; fwrite(data, len, 1, f); if (errno) { ERRS("unable to write output file"); goto out_flush; } DBG("firmware file \"%s\" completed", ofname); ret = EXIT_SUCCESS; out_flush: fflush(f); fclose(f); if (ret != EXIT_SUCCESS) { unlink(ofname); } out: return ret; } /* Helper functions to inspect_fw() representing different output formats */ inline void inspect_fw_pstr(const char *label, const char *str) { printf("%-23s: %s\n", label, str); } inline void inspect_fw_phex(const char *label, uint32_t val) { printf("%-23s: 0x%08x\n", label, val); } inline void inspect_fw_phexdec(const char *label, uint32_t val) { printf("%-23s: 0x%08x / %8u bytes\n", label, val, val); } inline void inspect_fw_pmd5sum(const char *label, const uint8_t *val, const char *text) { int i; printf("%-23s:", label); for (i=0; i<MD5SUM_LEN; i++) printf(" %02x", val[i]); printf(" %s\n", text); } // header_size = sizeof(struct fw_header) int build_fw(size_t header_size) { int buflen; char *buf; char *p; int ret = EXIT_FAILURE; int writelen = 0; writelen = header_size + kernel_len; if (combined) buflen = writelen; else buflen = layout->fw_max_len; buf = malloc(buflen); if (!buf) { ERR("no memory for buffer\n"); goto out; } memset(buf, 0xff, buflen); p = buf + header_size; ret = read_to_buf(&kernel_info, p); if (ret) goto out_free_buf; if (!combined) { p = buf + rootfs_ofs; ret = read_to_buf(&rootfs_info, p); if (ret) goto out_free_buf; writelen = rootfs_ofs + rootfs_info.file_size; if (add_jffs2_eof) writelen = pad_jffs2(buf, writelen, layout->fw_max_len); } if (!strip_padding) writelen = buflen; fill_header(buf, writelen); ret = write_fw(ofname, buf, writelen); if (ret) goto out_free_buf; ret = EXIT_SUCCESS; out_free_buf: free(buf); out: return ret; }