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