2017-08-25 11:54:18 +07:00
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
# XIP kernel .data segment compressor
|
|
|
|
#
|
|
|
|
# Created by: Nicolas Pitre, August 2017
|
|
|
|
# Copyright: (C) 2017 Linaro Limited
|
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License version 2 as
|
|
|
|
# published by the Free Software Foundation.
|
|
|
|
|
|
|
|
# This script locates the start of the .data section in xipImage and
|
|
|
|
# substitutes it with a compressed version. The needed offsets are obtained
|
|
|
|
# from symbol addresses in vmlinux. It is expected that .data extends to
|
|
|
|
# the end of xipImage.
|
|
|
|
|
|
|
|
set -e
|
|
|
|
|
|
|
|
VMLINUX="$1"
|
|
|
|
XIPIMAGE="$2"
|
|
|
|
|
|
|
|
DD="dd status=none"
|
|
|
|
|
|
|
|
# Use "make V=1" to debug this script.
|
|
|
|
case "$KBUILD_VERBOSE" in
|
|
|
|
*1*)
|
|
|
|
set -x
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
sym_val() {
|
|
|
|
# extract hex value for symbol in $1
|
2018-03-12 21:51:26 +07:00
|
|
|
local val=$($NM "$VMLINUX" 2>/dev/null | sed -n "/ $1\$/{s/ .*$//p;q}")
|
2017-08-25 11:54:18 +07:00
|
|
|
[ "$val" ] || { echo "can't find $1 in $VMLINUX" 1>&2; exit 1; }
|
|
|
|
# convert from hex to decimal
|
|
|
|
echo $((0x$val))
|
|
|
|
}
|
|
|
|
|
|
|
|
__data_loc=$(sym_val __data_loc)
|
|
|
|
_edata_loc=$(sym_val _edata_loc)
|
|
|
|
base_offset=$(sym_val _xiprom)
|
|
|
|
|
|
|
|
# convert to file based offsets
|
|
|
|
data_start=$(($__data_loc - $base_offset))
|
|
|
|
data_end=$(($_edata_loc - $base_offset))
|
|
|
|
|
|
|
|
# Make sure data occupies the last part of the file.
|
kbuild: Use ls(1) instead of stat(1) to obtain file size
stat(1) is not standardized and different implementations have their own
(conflicting) flags for querying the size of a file.
ls(1) provides the same information (value of st.st_size) in the 5th
column, except when the file is a character or block device. This output
is standardized[0]. The -n option turns on -l, which writes lines
formatted like
"%s %u %s %s %u %s %s\n", <file mode>, <number of links>,
<owner name>, <group name>, <size>, <date and time>,
<pathname>
but instead of writing the <owner name> and <group name>, it writes the
numeric owner and group IDs (this avoids /etc/passwd and /etc/group
lookups as well as potential field splitting issues).
The <size> field is specified as "the value that would be returned for
the file in the st_size field of struct stat".
To avoid duplicating logic in several locations in the tree, create
scripts/file-size.sh and update callers to use that instead of stat(1).
[0] http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html#tag_20_73_10
Signed-off-by: Michael Forney <forney@google.com>
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2018-03-19 07:54:02 +07:00
|
|
|
file_end=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" "$XIPIMAGE")
|
2017-08-25 11:54:18 +07:00
|
|
|
if [ "$file_end" != "$data_end" ]; then
|
|
|
|
printf "end of xipImage doesn't match with _edata_loc (%#x vs %#x)\n" \
|
2018-03-12 21:51:26 +07:00
|
|
|
$(($file_end + $base_offset)) $_edata_loc 1>&2
|
2017-08-25 11:54:18 +07:00
|
|
|
exit 1;
|
|
|
|
fi
|
|
|
|
|
|
|
|
# be ready to clean up
|
2018-03-12 21:51:26 +07:00
|
|
|
trap 'rm -f "$XIPIMAGE.tmp"; exit 1' 1 2 3
|
2017-08-25 11:54:18 +07:00
|
|
|
|
|
|
|
# substitute the data section by a compressed version
|
|
|
|
$DD if="$XIPIMAGE" count=$data_start iflag=count_bytes of="$XIPIMAGE.tmp"
|
|
|
|
$DD if="$XIPIMAGE" skip=$data_start iflag=skip_bytes |
|
|
|
|
gzip -9 >> "$XIPIMAGE.tmp"
|
|
|
|
|
|
|
|
# replace kernel binary
|
|
|
|
mv -f "$XIPIMAGE.tmp" "$XIPIMAGE"
|