install.sh 15.5 KB
Newer Older
1
#!/usr/bin/env bash
2

3
4
set -e

alex@thinkpad's avatar
alex@thinkpad committed
5
QEMU_NAME=${QEMU_NAME:=qemu-2.5.0}
6
ML=${ML:=magic-lantern}
7
GREP=${GREP:=grep}
8
ALLOW_64BIT_GDB=n
9
10
11
12
13
14

echo
echo "This will setup QEMU for emulating Magic Lantern."
echo "Thou shalt not be afraid of compiling stuff on Linux ;)"
echo -n "Continue? [y/n] "
read answer
15
16
17
if test "$answer" != "Y" -a "$answer" != "y"; then exit 0; fi
echo

18
function install_gdb {
19
20
21
22
23
24
    echo
    echo "*** Will download gcc-arm-none-eabi-5_4-2016q3 from:"
    echo "    https://developer.arm.com/open-source/gnu-toolchain/gnu-rm"
    echo

    TOOLCHAIN=gcc-arm-none-eabi-5_4-2016q3
25
26
    DOWNLOAD=https://launchpad.net/gcc-arm-embedded/5.0/5-2016-q3-update/+download/
    MIRROR=https://developer.arm.com/-/media/Files/downloads/gnu-rm/5_4-2016q3/
27
28
    UNTAR="tar -jxf"

29
    if [ $(uname) == "Darwin" ]; then
30
        TARBALL=gcc-arm-none-eabi-5_4-2016q3-20160926-mac.tar.bz2
31
32
33
    else
        TARBALL=gcc-arm-none-eabi-5_4-2016q3-20160926-linux.tar.bz2
    fi
34

35
36
    if [ ! -f ~/$TOOLCHAIN/bin/arm-none-eabi-gdb ]; then
        cd ~
37
38
        wget -c $DOWNLOAD$TARBALL || wget -c $MIRROR$TARBALL \
            && $UNTAR $TARBALL && rm $TARBALL
39
40
41
42
43
44
        cd -
    else
        echo "*** Toolchain already installed in:"
        echo "    ~/$TOOLCHAIN"
        echo
    fi
45

46
47
48
    echo "*** Please add gcc binaries to your executable PATH."
    echo "*** Run this command, or paste it into your .profile and reopen the terminal:"
    echo "    export PATH=~/$TOOLCHAIN/bin:\$PATH"
49
50
51
    echo
}

52
function valid_arm_gdb {
53
54
55
56
57
    if ! arm-none-eabi-gdb -v &> /dev/null; then
        # not installed, or not able to run for any reason
        return 1
    fi

58
59
60
61
62
63
64
    if [ "$ALLOW_64BIT_GDB" != "y" ]; then
        if arm-none-eabi-gdb -v | grep -q "host=x86_64"; then
            # 64-bit version - doesn't work
            # fixme: this may get printed more than once
            echo "*** WARNING: 64-bit GDB is known not to work."
            return 1
        fi
65
66
67
68
69
70
71
    fi

    # assume it's OK
    # todo: check version number
    return 0
}

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
function valid_arm_gcc {
    if ! arm-none-eabi-gcc -v &> /dev/null; then
        # not installed, or not able to run for any reason
        return 1
    fi

    echo "#include <stdlib.h>" > arm-gcc-test.c
    if ! arm-none-eabi-gcc -c arm-gcc-test.c; then
        echo "*** WARNING: your arm-none-eabi-gcc is unable to compile a simple program."
        rm arm-gcc-test.c
        return 1
    fi

    rm arm-gcc-test.c
    return 0
}

89
90
91
if [ $(uname) == "Darwin" ]; then
    echo "*** Installing dependencies for Mac..."
    echo
92
93
94
95
96
    # brew is "The missing package manager for macOS"
    # https://brew.sh
    if ! brew -v &> /dev/null; then
        ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
    fi
97
    
98
    packages="python wget mercurial xz grep pkg-config glib automake libtool pixman mtools"
99
100
101
102
    for pkg in $packages; do
        brew list $pkg &> /dev/null || brew install $pkg
    done
    
103
    GREP=ggrep
104
105
fi

alex@thinkpad's avatar
alex@thinkpad committed
106
if [  -n "$(lsb_release -i | grep Ubuntu)" ]; then
107
    # Ubuntu-based system? (including WSL)
108
109
110
    # install these packages, if not already
    # only request sudo if any of them is missing
    # instead of GTK (libgtk2.0-dev), you may prefer SDL (libsdl1.2-dev)
111
    packages="
112
        build-essential mercurial pkg-config libtool
113
        git libglib2.0-dev libpixman-1-dev zlib1g-dev
114
        libgtk2.0-dev xz-utils mtools netcat-openbsd
115
116
117
118
119
120
121
122
123
124
        python python-pip python-docutils"

    # if a valid arm-none-eabi-gcc/gdb is already in PATH, try to use that
    # otherwise, we'll try to install something
    if ! valid_arm_gdb || ! valid_arm_gcc; then
        echo "*** You do not seem to have an usable arm-none-eabi-gcc and/or gdb installed."
        echo "*** 64-bit GDB is known not to work, so you'll have to install a 32-bit one for now."
        echo
        echo "*** You have a few options:"
        echo
alex@thinkpad's avatar
alex@thinkpad committed
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

        # fixme: hidden options can still be selected
        if [  -z "$(uname -a | grep Microsoft)" ]; then
            echo "1 - Install gdb-arm-none-eabi:i386 and gcc-arm-none-eabi from Ubuntu repo (recommended)"
            echo "    This will install 32-bit binaries - will not work under Windows Subsystem for Linux."
            echo 
            echo "2 - Download a 32-bit gcc-arm-embedded and install it without the package manager."
            echo "    Will be installed in your home directory; to move it, you must edit the Makefiles."
            echo "    This will install 32-bit binaries - will not work under Windows Subsystem for Linux."
            echo
            if dpkg -l binutils-arm-none-eabi 2>/dev/null | grep -q '^.i'; then
                echo "3 - Remove Ubuntu toolchain and install the one from gcc-arm-embedded PPA (gcc 6.x)"
                echo "    This will:"
                echo "    - sudo apt-get remove gcc-arm-none-eabi gdb-arm-none-eabi \\"
                echo "           binutils-arm-none-eabi libnewlib-arm-none-eabi"
            else
                echo "3 - Install the toolchain from gcc-arm-embedded PPA (gcc 6.x)"
                echo "    This will:"
            fi
            echo "    - sudo add-apt-repository ppa:team-gcc-arm-embedded/ppa"
            echo "    - install the gcc-arm-embedded:i386 package."
            echo "    This will install 32-bit binaries - will not work under Windows Subsystem for Linux."
            echo
148
        fi
149
150
151
        echo "4 - Install gdb-arm-none-eabi and gcc-arm-none-eabi from Ubuntu repository (64-bit)"
        echo "    WARNING: this will not be able to run all our GDB scripts."
        echo 
152
        echo "5 - Manually install arm-none-eabi-gdb from https://launchpad.net/gcc-arm-embedded"
153
        echo "    or any other source, make sure it is in PATH, then run this script again."
154

155
156
157
158
159
160
161
162
        if ! arm-none-eabi-gdb -v &> /dev/null; then
            echo
        else
            echo
            echo "6 - Just use the current 64-bit toolchain."
            echo "    WARNING: this will not be able to run all our GDB scripts."
        fi

163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
        echo
        echo -n "Your choice? "
        read answer
        echo
        case $answer in
            1)
                # Ubuntu's 32-bit arm-none-eabi-gdb works fine
                # gcc-arm-none-eabi:i386 does not include libnewlib - Ubuntu bug?
                packages="$packages gdb-arm-none-eabi:i386 "
                packages="$packages gcc-arm-none-eabi libnewlib-arm-none-eabi"
                ;;
            2)
                # 32-bit gdb will be downloaded after installing these packages
                packages="$packages libc6:i386 libncurses5:i386"
                ;;
            3)
                # gcc-arm-embedded conflicts with gcc-arm-none-eabi
                # but the dependencies are not configured properly
                # so we have to fix the conflict manually...
                if dpkg -l binutils-arm-none-eabi 2>/dev/null | grep -q '^.i'; then
                    echo
                    echo "*** Please double-check - the following might remove additional packages!"
                    echo
                    sudo apt-get remove gcc-arm-none-eabi gdb-arm-none-eabi \
                         binutils-arm-none-eabi libnewlib-arm-none-eabi
                fi
189
                packages="$packages gcc-arm-embedded:i386"
190
191
192
193
194
                echo
                echo "*** Adding the team-gcc-arm-embedded PPA repository..."
                echo "    sudo add-apt-repository ppa:team-gcc-arm-embedded/ppa"
                echo
                sudo add-apt-repository ppa:team-gcc-arm-embedded/ppa
195
196
197
198
199
                ;;
            4)
                # Ubuntu's 64-bit arm-none-eabi-gdb is... well... better than nothing
                packages="$packages gdb-arm-none-eabi:amd64"
                packages="$packages gcc-arm-none-eabi:amd64 libnewlib-arm-none-eabi"
200
                ALLOW_64BIT_GDB=y
201
                ;;
202
203
            5)
                # user will install arm-none-eabi-gdb and run the script again
204
205
                exit 0
                ;;
206
207
            6)
                # use the installed version, even though it's known not to work
208
                ALLOW_64BIT_GDB=y
209
                ;;
210
            *)
211
                # invalid choice
212
213
214
215
216
217
218
                exit 1
                ;;
        esac
    else
        echo "*** You have a valid ARM GCC/GDB already installed - using that one."
    fi

219
220
    echo "*** Checking dependencies for Ubuntu..."
    echo
221
222
223
    # https://wiki.debian.org/ListInstalledPackages
    # dpkg -l also returns packages that are not installed
    deps_installed=yes
224
    for package in $packages; do
225
226
227
        if ! dpkg -l $package 2>/dev/null | grep -q '^.i'; then
            echo Not installed: $package
            deps_installed=no
228
229
        fi
    done
230
231
232
233
234

    if [ "$deps_installed" == "no" ]; then
        echo
        echo "*** Installing dependencies for Ubuntu..."
        echo
235
236
237
        if [[ "$packages" == *i386* ]]; then
            sudo dpkg --add-architecture i386
        fi 
238
        sudo apt-get update
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
        sudo apt-get install $packages
        echo
    fi

    deps_installed=yes
    for package in $packages; do
        if ! dpkg -l $package 2>/dev/null | grep -q '^.i'; then
            echo Not installed: $package
            deps_installed=no
        fi
    done

    if [ "$deps_installed" == "no" ]; then
        echo
        echo "*** Error: Ubuntu dependencies could not be installed."
254
        echo
255
        exit 1
256
    fi
257
258
fi

259
# all systems (including Mac, or Ubuntu if the installation from repositories failed)
260
# this one works on old systems as well, but it won't work under WSL
261
if ! valid_arm_gdb; then
262
    echo
263
264
    echo "*** WARNING: a valid arm-none-eabi-gdb could not be found."
    echo "*** Downloading a toolchain and installing it without the package manager."
265
    echo "*** Will be installed in your home directory (Makefile.user.default expects it there)."
266
267
    echo
    install_gdb
268
269
fi

270
# make sure we have a valid arm-none-eabi-gdb (regardless of operating system)
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
if ! valid_arm_gdb; then
    if ! arm-none-eabi-gdb -v &> /dev/null; then
        echo "*** Please set up a valid arm-none-eabi-gdb before continuing."
        exit 1
    else
        # valid_arm_gdb will print why the current one is not good
        echo -n "Continue anyway? [y/N] "
        read answer
        if test "$answer" != "Y" -a "$answer" != "y"; then exit 1; fi
        echo
    fi
fi

# same for arm-none-eabi-gcc
if ! valid_arm_gcc; then
    echo "*** Please set up a valid arm-none-eabi-gcc before continuing."
287
288
289
    exit 1
fi

290
echo
291
292
293
echo -n "*** Using GDB: "
command -v arm-none-eabi-gdb
arm-none-eabi-gdb -v | head -n1
294
295
296
echo
echo -n "*** Using GCC: "
command -v arm-none-eabi-gcc
297
arm-none-eabi-gcc -v 2>&1 | grep "gcc version"
298
echo
299

300
# install docutils (for compiling ML modules) and vncdotool (for test suite)
301
302
303
# only install if any of them is missing
pip2 list | grep docutils  || rst2html -h  > /dev/null || pip2 install docutils
pip2 list | grep vncdotool || vncdotool -h > /dev/null || pip2 install vncdotool
304

305
306
function die { echo "${1:-"Unknown Error"}" 1>&2 ; exit 1; }

307
pwd | grep $ML/contrib/qemu > /dev/null || die "error: we should be in $ML/contrib/qemu"
308
309
310

# go to the parent of magic-lantern folder
cd ../../..
311
ls | $GREP $ML > /dev/null || die "error: expecting to find $ML here"
312

313
mkdir -p qemu
314
315
316
cd qemu

echo
317
echo "*** Setting up QEMU in $(pwd)..."
318
319
echo

320
if [ -d $QEMU_NAME ]; then
321
  DATE=`date '+%Y-%m-%d-%H-%M-%S'`
322
323
  echo "*** Directory $(pwd)/$QEMU_NAME already exists."
  echo "*** To reinstall, please rename or delete it, then run this script again."
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
  echo "*** You can enter \"D\" (uppercase!) now to delete the directory automatically"
  echo "*** or \"R\"|\"r\" to rename it to $(pwd)/$QEMU_NAME-$DATE."
  echo "*** Everything else will cancel the operation."
  read answer
  case "$answer" in
      D)
        rm -Rf $QEMU_NAME
        ;;
      R|r)
        mv $QEMU_NAME $QEMU_NAME-$DATE
        ;;
      *)
        exit 1
        ;;
  esac
339
340
fi

341
# get qemu
342
wget -q --show-progress --progress=dot:giga -c http://wiki.qemu-project.org/download/$QEMU_NAME.tar.bz2
343
echo
344
tar jxf $QEMU_NAME.tar.bz2
345
echo
346
347
# initialize a git repo, to make it easy to track changes to QEMU source
cd $QEMU_NAME
348
349
350
351
if [ ! -d .git ]; then
  git init
  # git requires a valid email; if not setup, add one for this directory only
  git config user.email || git config user.email qemu@magiclantern.fm
352
  git add . && git commit -q -m "$QEMU_NAME vanilla"
353
fi
354
355
cd ..

356
357
echo "Copying files..."

358
# copy our helper scripts
359
cp -r ../$ML/contrib/qemu/scripts/* .
360
chmod +x *.sh
361
362
363

# copy our testing scripts
mkdir -p tests
364
cp -r ../$ML/contrib/qemu/tests/* tests/
365
366
367
chmod +x tests/*.sh

# apply our patch
368
cd ${QEMU_NAME}
369
mkdir -p hw/eos
370
371
cp -r ../../$ML/contrib/qemu/eos/* hw/eos/
cp -r ../../$ML/src/backtrace.[ch] hw/eos/dbi/
372
373
374
375
376
if gcc -v 2>&1 | grep -q "gcc version 7"; then
  patch -N -p1 < ../../$ML/contrib/qemu/$QEMU_NAME-gcc7.patch
  git add -u . && git commit -q -m "$QEMU_NAME patched for gcc 7.x"
fi

377
patch -N -p1 < ../../$ML/contrib/qemu/$QEMU_NAME.patch
378
379
# don't commit this one - we'll use "git diff" to update the above patch

380
381
cd ..

382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
# setup the card image
if [ ! -f "sd.img" ]; then
    echo "Setting up SD card image..."
    cp -v ../$ML/contrib/qemu/sd.img.xz .
    unxz -v sd.img.xz
else
    echo "SD image already exists, skipping."
fi

if [ ! -f "cf.img" ]; then
    echo "Setting up CF card image..."
    cp -v sd.img cf.img
else
    echo "CF image already exists, skipping."
fi

398
399
400
401
402
403
echo ""
echo "Next steps:"
echo "==========="
echo
echo "1) Compile QEMU"
echo
404
echo "   cd `pwd`/${QEMU_NAME}"
405
echo "   ../configure_eos.sh"
406
echo "   make -j`$GREP -c processor /proc/cpuinfo 2> /dev/null || sysctl -n hw.ncpu 2> /dev/null || echo 1`"
407
408
409
410
411
echo
echo "2) Grab a copy of the Canon firmware from your own camera"
echo "   (don't request one and don't share it online - it's copyrighted)"
echo
echo "   Look on your SD card - you should find ML/LOGS/ROM0.BIN and ROM1.BIN"
412
413
echo "   Copy them under your camera model's subdirectory, for example:"
echo "   `pwd`/60D/"
414
echo
415
416
echo "   For models that use a serial flash, you may have to dump its contents"
echo "   using the sf_dump module, then copy SFDATA.BIN as well."
417
echo
418
echo "3) Install Magic Lantern on your SD/CF card image:"
419
echo
420
echo "   make -C ../magic-lantern 60D_install_qemu "
421
echo
422
423
echo "   The included card image is bootable and contains a small autoexec.bin"
echo "   that runs on all supported EOS cameras and prints some basic info."
424
echo
425
echo "4) Start emulation with:"
426
427
echo
echo "   cd `pwd`/"
428
429
430
echo "   ./run_canon_fw.sh 60D"
echo
echo "   This will recompile QEMU, but not ML."
431
echo
432
echo "   Note: Canon GUI emulation (menu navigation, no LiveView) only works on:"
433
echo -n "   "; echo $($GREP --color=never -oPz "(?<=GUI_CAMS=\( )[^()]*(?=\))" tests/run_tests.sh | tr '\0' '\n');
434
echo
435
echo "5) Tips & tricks:"
436
437
echo "   - to enable or disable the boot flag in ROM, use something like:"
echo "     ./run_canon_fw.sh 60D,firmware=\"boot=1\""
438
439
echo "   - to use multiple firmware versions, place the ROMs under e.g. 5D3/113/ROM*.BIN and run:"
echo "     ./run_canon_fw.sh 5D3,firmware=\"113;boot=1\""
440
441
442
443
444
echo "   - to show MMIO activity (registers) and interrupts, use:"
echo "     ./run_canon_fw.sh 60D -d io,int"
echo "   - to show the executed ASM code, step by step, use:"
echo "     ./run_canon_fw.sh 60D -d exec,int -singlestep"
echo "   - to trace debug messages and various functions in the firmware, use:"
445
echo "     ./run_canon_fw.sh 60D -d debugmsg -s -S & arm-none-eabi-gdb -x 60D/debugmsg.gdb"
446
447
echo "   - some camera models require GDB patches to bypass tricky code sequences:"
echo "     ./run_canon_fw.sh 700D -s -S & arm-none-eabi-gdb -x 700D/patches.gdb"
448
449
450
451
echo
echo "Online documentation: "
echo
echo "   https://bitbucket.org/hudson/magic-lantern/src/qemu/contrib/qemu/" 
452
453
echo
echo "Enjoy!"