xref: /aosp_15_r20/frameworks/base/tools/obbtool/mkobb.sh (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1*d57664e9SAndroid Build Coastguard Worker#!/bin/bash
2*d57664e9SAndroid Build Coastguard Worker#
3*d57664e9SAndroid Build Coastguard Worker# Copyright (C) 2010 The Android Open Source Project
4*d57664e9SAndroid Build Coastguard Worker#
5*d57664e9SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
6*d57664e9SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
7*d57664e9SAndroid Build Coastguard Worker# You may obtain a copy of the License at
8*d57664e9SAndroid Build Coastguard Worker
9*d57664e9SAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
10*d57664e9SAndroid Build Coastguard Worker#
11*d57664e9SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
12*d57664e9SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
13*d57664e9SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*d57664e9SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
15*d57664e9SAndroid Build Coastguard Worker# limitations under the License.
16*d57664e9SAndroid Build Coastguard Worker#
17*d57664e9SAndroid Build Coastguard Worker
18*d57664e9SAndroid Build Coastguard Worker# mkobb.sh - Creates OBB files on Linux machines
19*d57664e9SAndroid Build Coastguard Worker
20*d57664e9SAndroid Build Coastguard Worker# Directory where we should temporarily mount the OBB loopback to copy files
21*d57664e9SAndroid Build Coastguard WorkerMOUNTDIR=/tmp
22*d57664e9SAndroid Build Coastguard Worker
23*d57664e9SAndroid Build Coastguard Worker# Presets. Changing these will probably break your OBB on the device
24*d57664e9SAndroid Build Coastguard WorkerCRYPTO=twofish
25*d57664e9SAndroid Build Coastguard WorkerFS=vfat
26*d57664e9SAndroid Build Coastguard WorkerMKFS=mkfs.vfat
27*d57664e9SAndroid Build Coastguard WorkerLOSETUP=losetup
28*d57664e9SAndroid Build Coastguard WorkerBLOCK_SIZE=512
29*d57664e9SAndroid Build Coastguard WorkerSLOP=512 # Amount of filesystem slop in ${BLOCK_SIZE} blocks
30*d57664e9SAndroid Build Coastguard Worker
31*d57664e9SAndroid Build Coastguard Workerfind_binaries() {
32*d57664e9SAndroid Build Coastguard Worker    MKFSBIN=`which ${MKFS}`
33*d57664e9SAndroid Build Coastguard Worker    LOSETUPBIN=`which ${LOSETUP}`
34*d57664e9SAndroid Build Coastguard Worker    MOUNTBIN=`which mount`
35*d57664e9SAndroid Build Coastguard Worker    UMOUNTBIN=`which umount`
36*d57664e9SAndroid Build Coastguard Worker    DDBIN=`which dd`
37*d57664e9SAndroid Build Coastguard Worker    RSYNCBIN=`which rsync`
38*d57664e9SAndroid Build Coastguard Worker    PBKDF2GEN=`which pbkdf2gen`
39*d57664e9SAndroid Build Coastguard Worker}
40*d57664e9SAndroid Build Coastguard Worker
41*d57664e9SAndroid Build Coastguard Workercheck_prereqs() {
42*d57664e9SAndroid Build Coastguard Worker    if [ "`uname -s`x" != "Linuxx" ]; then \
43*d57664e9SAndroid Build Coastguard Worker        echo "ERROR: This script only works on Linux!"
44*d57664e9SAndroid Build Coastguard Worker        exit 1
45*d57664e9SAndroid Build Coastguard Worker    fi
46*d57664e9SAndroid Build Coastguard Worker
47*d57664e9SAndroid Build Coastguard Worker    if ! egrep -q "^cryptoloop " /proc/modules; then \
48*d57664e9SAndroid Build Coastguard Worker        echo "ERROR: Could not find cryptoloop in the kernel."
49*d57664e9SAndroid Build Coastguard Worker        echo "Perhaps you need to: modprobe cryptoloop"
50*d57664e9SAndroid Build Coastguard Worker        exit 1
51*d57664e9SAndroid Build Coastguard Worker    fi
52*d57664e9SAndroid Build Coastguard Worker
53*d57664e9SAndroid Build Coastguard Worker    if ! egrep -q "name\s*:\s*${CRYPTO}$" /proc/crypto; then \
54*d57664e9SAndroid Build Coastguard Worker        echo "ERROR: Could not find crypto \`${CRYPTO}' in the kernel."
55*d57664e9SAndroid Build Coastguard Worker        echo "Perhaps you need to: modprobe ${CRYPTO}"
56*d57664e9SAndroid Build Coastguard Worker        exit 1
57*d57664e9SAndroid Build Coastguard Worker    fi
58*d57664e9SAndroid Build Coastguard Worker
59*d57664e9SAndroid Build Coastguard Worker    if ! egrep -q "^\s*${FS}$" /proc/filesystems; then \
60*d57664e9SAndroid Build Coastguard Worker        echo "ERROR: Could not find filesystem \`${FS}' in the kernel."
61*d57664e9SAndroid Build Coastguard Worker        echo "Perhaps you need to: modprobe ${FS}"
62*d57664e9SAndroid Build Coastguard Worker        exit 1
63*d57664e9SAndroid Build Coastguard Worker    fi
64*d57664e9SAndroid Build Coastguard Worker
65*d57664e9SAndroid Build Coastguard Worker    if [ "${MKFSBIN}x" = "x" ]; then \
66*d57664e9SAndroid Build Coastguard Worker        echo "ERROR: Could not find ${MKFS} in your path!"
67*d57664e9SAndroid Build Coastguard Worker        exit 1
68*d57664e9SAndroid Build Coastguard Worker    elif [ ! -x "${MKFSBIN}" ]; then \
69*d57664e9SAndroid Build Coastguard Worker        echo "ERROR: ${MKFSBIN} is not executable!"
70*d57664e9SAndroid Build Coastguard Worker        exit 1
71*d57664e9SAndroid Build Coastguard Worker    fi
72*d57664e9SAndroid Build Coastguard Worker
73*d57664e9SAndroid Build Coastguard Worker    if [ "${LOSETUPBIN}x" = "x" ]; then \
74*d57664e9SAndroid Build Coastguard Worker        echo "ERROR: Could not find ${LOSETUP} in your path!"
75*d57664e9SAndroid Build Coastguard Worker        exit 1
76*d57664e9SAndroid Build Coastguard Worker    elif [ ! -x "${LOSETUPBIN}" ]; then \
77*d57664e9SAndroid Build Coastguard Worker        echo "ERROR: ${LOSETUPBIN} is not executable!"
78*d57664e9SAndroid Build Coastguard Worker        exit 1
79*d57664e9SAndroid Build Coastguard Worker    fi
80*d57664e9SAndroid Build Coastguard Worker
81*d57664e9SAndroid Build Coastguard Worker    if [ "${PBKDF2GEN}x" = "x" ]; then \
82*d57664e9SAndroid Build Coastguard Worker        echo "ERROR: Could not find pbkdf2gen in your path!"
83*d57664e9SAndroid Build Coastguard Worker        exit 1
84*d57664e9SAndroid Build Coastguard Worker    fi
85*d57664e9SAndroid Build Coastguard Worker}
86*d57664e9SAndroid Build Coastguard Worker
87*d57664e9SAndroid Build Coastguard Workercleanup() {
88*d57664e9SAndroid Build Coastguard Worker    if [ "${loopdev}x" != "x" ]; then \
89*d57664e9SAndroid Build Coastguard Worker        ${LOSETUPBIN} -d ${loopdev}
90*d57664e9SAndroid Build Coastguard Worker    fi
91*d57664e9SAndroid Build Coastguard Worker}
92*d57664e9SAndroid Build Coastguard Worker
93*d57664e9SAndroid Build Coastguard Workerhidden_prompt() {
94*d57664e9SAndroid Build Coastguard Worker    unset output
95*d57664e9SAndroid Build Coastguard Worker    prompt="$1"
96*d57664e9SAndroid Build Coastguard Worker    outvar="$2"
97*d57664e9SAndroid Build Coastguard Worker    while read -s -n 1 -p "$prompt" c; do \
98*d57664e9SAndroid Build Coastguard Worker        if [ "x$c" = "x" ]; then \
99*d57664e9SAndroid Build Coastguard Worker            break
100*d57664e9SAndroid Build Coastguard Worker        fi
101*d57664e9SAndroid Build Coastguard Worker        prompt='*'
102*d57664e9SAndroid Build Coastguard Worker        output="${output}${c}"
103*d57664e9SAndroid Build Coastguard Worker    done
104*d57664e9SAndroid Build Coastguard Worker    echo
105*d57664e9SAndroid Build Coastguard Worker    eval $outvar="$output"
106*d57664e9SAndroid Build Coastguard Worker    unset output
107*d57664e9SAndroid Build Coastguard Worker}
108*d57664e9SAndroid Build Coastguard Worker
109*d57664e9SAndroid Build Coastguard Workerread_key() {
110*d57664e9SAndroid Build Coastguard Worker    hidden_prompt "        Encryption key: " key
111*d57664e9SAndroid Build Coastguard Worker
112*d57664e9SAndroid Build Coastguard Worker    if [ "${key}x" = "x" ]; then \
113*d57664e9SAndroid Build Coastguard Worker        echo "ERROR: An empty key is not allowed!"
114*d57664e9SAndroid Build Coastguard Worker        exit 1
115*d57664e9SAndroid Build Coastguard Worker    fi
116*d57664e9SAndroid Build Coastguard Worker
117*d57664e9SAndroid Build Coastguard Worker    hidden_prompt "Encryption key (again): " key2
118*d57664e9SAndroid Build Coastguard Worker
119*d57664e9SAndroid Build Coastguard Worker    if [ "${key}x" != "${key2}x" ]; then \
120*d57664e9SAndroid Build Coastguard Worker        echo "ERROR: Encryption keys do not match!"
121*d57664e9SAndroid Build Coastguard Worker        exit 1
122*d57664e9SAndroid Build Coastguard Worker    fi
123*d57664e9SAndroid Build Coastguard Worker}
124*d57664e9SAndroid Build Coastguard Worker
125*d57664e9SAndroid Build Coastguard Workeronexit() {
126*d57664e9SAndroid Build Coastguard Worker    if [ "x${temp_mount}" != "x" ]; then \
127*d57664e9SAndroid Build Coastguard Worker        ${UMOUNTBIN} ${temp_mount}
128*d57664e9SAndroid Build Coastguard Worker        rmdir ${temp_mount}
129*d57664e9SAndroid Build Coastguard Worker    fi
130*d57664e9SAndroid Build Coastguard Worker    if [ "x${loop_dev}" != "x" ]; then \
131*d57664e9SAndroid Build Coastguard Worker        if [ ${use_crypto} -eq 1 ]; then \
132*d57664e9SAndroid Build Coastguard Worker            dmsetup remove -f ${loop_dev}
133*d57664e9SAndroid Build Coastguard Worker            ${LOSETUPBIN} -d ${old_loop_dev}
134*d57664e9SAndroid Build Coastguard Worker        else \
135*d57664e9SAndroid Build Coastguard Worker            ${LOSETUPBIN} -d ${loop_dev}
136*d57664e9SAndroid Build Coastguard Worker        fi
137*d57664e9SAndroid Build Coastguard Worker    fi
138*d57664e9SAndroid Build Coastguard Worker    if [ "x${tempfile}" != "x" -a -f "${tempfile}" ]; then \
139*d57664e9SAndroid Build Coastguard Worker        rm -f ${tempfile}
140*d57664e9SAndroid Build Coastguard Worker    fi
141*d57664e9SAndroid Build Coastguard Worker    if [ "x${keyfile}" != "x" -a -f "${keyfile}" ]; then \
142*d57664e9SAndroid Build Coastguard Worker        rm -f ${keyfile}
143*d57664e9SAndroid Build Coastguard Worker    fi
144*d57664e9SAndroid Build Coastguard Worker    echo "Fatal error."
145*d57664e9SAndroid Build Coastguard Worker    exit 1
146*d57664e9SAndroid Build Coastguard Worker}
147*d57664e9SAndroid Build Coastguard Worker
148*d57664e9SAndroid Build Coastguard Workerusage() {
149*d57664e9SAndroid Build Coastguard Worker    echo "mkobb.sh -- Create OBB files for use on Android"
150*d57664e9SAndroid Build Coastguard Worker    echo ""
151*d57664e9SAndroid Build Coastguard Worker    echo " -d <directory> Use <directory> as input for OBB files"
152*d57664e9SAndroid Build Coastguard Worker    echo " -k <key>       Use <key> to encrypt OBB file"
153*d57664e9SAndroid Build Coastguard Worker    echo " -K             Prompt for key to encrypt OBB file"
154*d57664e9SAndroid Build Coastguard Worker    echo " -o <filename>  Write OBB file out to <filename>"
155*d57664e9SAndroid Build Coastguard Worker    echo " -v             Verbose mode"
156*d57664e9SAndroid Build Coastguard Worker    echo " -h             Help; this usage screen"
157*d57664e9SAndroid Build Coastguard Worker}
158*d57664e9SAndroid Build Coastguard Worker
159*d57664e9SAndroid Build Coastguard Workerfind_binaries
160*d57664e9SAndroid Build Coastguard Workercheck_prereqs
161*d57664e9SAndroid Build Coastguard Worker
162*d57664e9SAndroid Build Coastguard Workeruse_crypto=0
163*d57664e9SAndroid Build Coastguard Worker
164*d57664e9SAndroid Build Coastguard Workerargs=`getopt -o d:hk:Ko:v -- "$@"`
165*d57664e9SAndroid Build Coastguard Workereval set -- "$args"
166*d57664e9SAndroid Build Coastguard Worker
167*d57664e9SAndroid Build Coastguard Workerwhile true; do \
168*d57664e9SAndroid Build Coastguard Worker    case "$1" in
169*d57664e9SAndroid Build Coastguard Worker        -d) directory=$2; shift 2;;
170*d57664e9SAndroid Build Coastguard Worker        -h) usage; exit 1;;
171*d57664e9SAndroid Build Coastguard Worker        -k) key=$2; use_crypto=1; shift 2;;
172*d57664e9SAndroid Build Coastguard Worker        -K) prompt_key=1; use_crypto=1; shift;;
173*d57664e9SAndroid Build Coastguard Worker        -v) verbose=1; shift;;
174*d57664e9SAndroid Build Coastguard Worker        -o) filename=$2; shift 2;;
175*d57664e9SAndroid Build Coastguard Worker        --) shift; break;;
176*d57664e9SAndroid Build Coastguard Worker        *) echo "ERROR: Invalid argument in option parsing! Cannot recover. Ever."; exit 1;;
177*d57664e9SAndroid Build Coastguard Worker    esac
178*d57664e9SAndroid Build Coastguard Workerdone
179*d57664e9SAndroid Build Coastguard Worker
180*d57664e9SAndroid Build Coastguard Workerif [ "${directory}x" = "x" -o ! -d "${directory}" ]; then \
181*d57664e9SAndroid Build Coastguard Worker    echo "ERROR: Must specify valid input directory"
182*d57664e9SAndroid Build Coastguard Worker    echo ""
183*d57664e9SAndroid Build Coastguard Worker    usage
184*d57664e9SAndroid Build Coastguard Worker    exit 1;
185*d57664e9SAndroid Build Coastguard Workerfi
186*d57664e9SAndroid Build Coastguard Worker
187*d57664e9SAndroid Build Coastguard Workerif [ "${filename}x" = "x" ]; then \
188*d57664e9SAndroid Build Coastguard Worker    echo "ERROR: Must specify filename"
189*d57664e9SAndroid Build Coastguard Worker    echo ""
190*d57664e9SAndroid Build Coastguard Worker    usage
191*d57664e9SAndroid Build Coastguard Worker    exit 1;
192*d57664e9SAndroid Build Coastguard Workerfi
193*d57664e9SAndroid Build Coastguard Worker
194*d57664e9SAndroid Build Coastguard Workerif [ ${use_crypto} -eq 1 -a "${key}x" = "x" -a 0${prompt_key} -eq 0 ]; then \
195*d57664e9SAndroid Build Coastguard Worker    echo "ERROR: Crypto desired, but no key supplied or requested to prompt for."
196*d57664e9SAndroid Build Coastguard Worker    exit 1
197*d57664e9SAndroid Build Coastguard Workerfi
198*d57664e9SAndroid Build Coastguard Worker
199*d57664e9SAndroid Build Coastguard Workerif [ 0${prompt_key} -eq 1 ]; then \
200*d57664e9SAndroid Build Coastguard Worker    read_key
201*d57664e9SAndroid Build Coastguard Workerfi
202*d57664e9SAndroid Build Coastguard Worker
203*d57664e9SAndroid Build Coastguard Workeroutdir=`dirname ${filename}`
204*d57664e9SAndroid Build Coastguard Workerif [ ! -d "${outdir}" ]; then \
205*d57664e9SAndroid Build Coastguard Worker    echo "ERROR: Output directory does not exist: ${outdir}"
206*d57664e9SAndroid Build Coastguard Worker    exit 1
207*d57664e9SAndroid Build Coastguard Workerfi
208*d57664e9SAndroid Build Coastguard Worker
209*d57664e9SAndroid Build Coastguard Worker# Make sure we clean up any stuff we create from here on during error conditions
210*d57664e9SAndroid Build Coastguard Workertrap onexit ERR
211*d57664e9SAndroid Build Coastguard Worker
212*d57664e9SAndroid Build Coastguard Workertempfile=$(tempfile -d ${outdir}) || ( echo "ERROR: couldn't create temporary file in ${outdir}"; exit 1 )
213*d57664e9SAndroid Build Coastguard Worker
214*d57664e9SAndroid Build Coastguard Workerblock_count=`du -s --apparent-size --block-size=512 ${directory} | awk '{ print $1; }'`
215*d57664e9SAndroid Build Coastguard Workerif [ $? -ne 0 ]; then \
216*d57664e9SAndroid Build Coastguard Worker    echo "ERROR: Couldn't read size of input directory ${directory}"
217*d57664e9SAndroid Build Coastguard Worker    exit 1
218*d57664e9SAndroid Build Coastguard Workerfi
219*d57664e9SAndroid Build Coastguard Worker
220*d57664e9SAndroid Build Coastguard Workerecho "Creating temporary file..."
221*d57664e9SAndroid Build Coastguard Worker${DDBIN} if=/dev/zero of=${tempfile} bs=${BLOCK_SIZE} count=$((${block_count} + ${SLOP})) > /dev/null 2>&1
222*d57664e9SAndroid Build Coastguard Workerif [ $? -ne 0 ]; then \
223*d57664e9SAndroid Build Coastguard Worker    echo "ERROR: creating temporary file: $?"
224*d57664e9SAndroid Build Coastguard Workerfi
225*d57664e9SAndroid Build Coastguard Worker
226*d57664e9SAndroid Build Coastguard Workerloop_dev=$(${LOSETUPBIN} -f) || ( echo "ERROR: losetup wouldn't tell us the next unused device"; exit 1 )
227*d57664e9SAndroid Build Coastguard Worker
228*d57664e9SAndroid Build Coastguard Worker${LOSETUPBIN} ${loop_dev} ${tempfile} || ( echo "ERROR: couldn't create loopback device"; exit 1 )
229*d57664e9SAndroid Build Coastguard Worker
230*d57664e9SAndroid Build Coastguard Workerif [ ${use_crypto} -eq 1 ]; then \
231*d57664e9SAndroid Build Coastguard Worker    eval `${PBKDF2GEN} ${key}`
232*d57664e9SAndroid Build Coastguard Worker    unique_dm_name=`basename ${tempfile}`
233*d57664e9SAndroid Build Coastguard Worker    echo "0 `blockdev --getsize ${loop_dev}` crypt ${CRYPTO} ${key} 0 ${loop_dev} 0" | dmsetup create ${unique_dm_name}
234*d57664e9SAndroid Build Coastguard Worker    old_loop_dev=${loop_dev}
235*d57664e9SAndroid Build Coastguard Worker    loop_dev=/dev/mapper/${unique_dm_name}
236*d57664e9SAndroid Build Coastguard Workerfi
237*d57664e9SAndroid Build Coastguard Worker
238*d57664e9SAndroid Build Coastguard Worker#
239*d57664e9SAndroid Build Coastguard Worker# Create the filesystem
240*d57664e9SAndroid Build Coastguard Worker#
241*d57664e9SAndroid Build Coastguard Workerecho ""
242*d57664e9SAndroid Build Coastguard Worker${MKFSBIN} -I ${loop_dev}
243*d57664e9SAndroid Build Coastguard Workerecho ""
244*d57664e9SAndroid Build Coastguard Worker
245*d57664e9SAndroid Build Coastguard Worker#
246*d57664e9SAndroid Build Coastguard Worker# Make the temporary mount point and mount it
247*d57664e9SAndroid Build Coastguard Worker#
248*d57664e9SAndroid Build Coastguard Workertemp_mount="${MOUNTDIR}/${RANDOM}"
249*d57664e9SAndroid Build Coastguard Workermkdir ${temp_mount}
250*d57664e9SAndroid Build Coastguard Worker${MOUNTBIN} -t ${FS} -o loop ${loop_dev} ${temp_mount}
251*d57664e9SAndroid Build Coastguard Worker
252*d57664e9SAndroid Build Coastguard Worker#
253*d57664e9SAndroid Build Coastguard Worker# rsync the files!
254*d57664e9SAndroid Build Coastguard Worker#
255*d57664e9SAndroid Build Coastguard Workerecho "Copying files:"
256*d57664e9SAndroid Build Coastguard Worker${RSYNCBIN} -av --no-owner --no-group ${directory}/ ${temp_mount}/
257*d57664e9SAndroid Build Coastguard Workerecho ""
258*d57664e9SAndroid Build Coastguard Worker
259*d57664e9SAndroid Build Coastguard Workerecho "Successfully created \`${filename}'"
260*d57664e9SAndroid Build Coastguard Worker
261*d57664e9SAndroid Build Coastguard Workerif [ ${use_crypto} -eq 1 ]; then \
262*d57664e9SAndroid Build Coastguard Worker    echo "salt for use with obbtool is:"
263*d57664e9SAndroid Build Coastguard Worker    echo "${salt}"
264*d57664e9SAndroid Build Coastguard Workerfi
265*d57664e9SAndroid Build Coastguard Worker
266*d57664e9SAndroid Build Coastguard Worker#
267*d57664e9SAndroid Build Coastguard Worker# Undo all the temporaries
268*d57664e9SAndroid Build Coastguard Worker#
269*d57664e9SAndroid Build Coastguard Workerumount ${temp_mount}
270*d57664e9SAndroid Build Coastguard Workerrmdir ${temp_mount}
271*d57664e9SAndroid Build Coastguard Workerif [ ${use_crypto} -eq 1 ]; then \
272*d57664e9SAndroid Build Coastguard Worker    dmsetup remove -f ${loop_dev}
273*d57664e9SAndroid Build Coastguard Worker    ${LOSETUPBIN} -d ${old_loop_dev}
274*d57664e9SAndroid Build Coastguard Workerelse \
275*d57664e9SAndroid Build Coastguard Worker    ${LOSETUPBIN} -d ${loop_dev}
276*d57664e9SAndroid Build Coastguard Workerfi
277*d57664e9SAndroid Build Coastguard Workermv ${tempfile} ${filename}
278*d57664e9SAndroid Build Coastguard Worker
279*d57664e9SAndroid Build Coastguard Workertrap - ERR
280*d57664e9SAndroid Build Coastguard Worker
281*d57664e9SAndroid Build Coastguard Workerexit 0
282