The Nvidia Shield TV Box offers 256 CUDA cores delivering over 1 TeraFLOPs of performance for around 200 €. Great value for mobile deep learning experiments – if only a standard linux would run on it. Fortunately some people over at XDA-Developers have figured out a way to do just that. The instructions are however assuming much previous knowledge, which is why I attempted to compile a recipe here with everything in one place.
For some of the cross compiling you will either need a native Ubuntu Trusty x64 machine or a VM. As I don’t have a x64 machine with Ubuntu Trusty, I will go the VM route. I hate Virtual Box and its laggy awkward UI. Fortunately I have revently discovered vagrant, which automates and hides many of those things.
0. Installing and connecting to a Trusty x64 VM is now as easy as:
1 2 3 4 |
brew cask install virtualbox vagrant vagrant init ubuntu/trusty64 vagrant up vagrant ssh |
Unfortunately the memory of the VM is too small for compiling the kernel, so edit the vagrant file to add some more ram and cpus and the ability to capture sdcardreaders:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
nano ~/Vagrantfile config.vm.provider "virtualbox" do |vb| vb.memory = "8192" vb.cpus = 2 vb.customize ["modifyvm", :id, "--usb", "on"] vb.customize ["modifyvm", :id, "--usbehci", "on"] vb.customize ["usbfilter", "add", "0", "--target", :id, "--name", "Any Mass Storage Device", "--manufacturer", "Generic", "--product", "Mass Storage Device"] vb.customize ["usbfilter", "add", "0", "--target", :id, "--name", "Nvidia Shield TV", "--vendorid", "0x10DE", "--product", "Tegra Device"] end |
Further hints for designing filters can be obtained by:
1 |
VBoxManage list usbhost |
Unmount the sd card reader from the host system and reload vagrant to restart with the new config:
1 2 3 4 |
diskutil list sudo diskutil unmountDisk /dev/diskX vagrant reload vagrant ssh |
1. Now we can prepare a MicroSD card with the operating system. First identify your sd card reader, init the sd card with ext4 and mount it:
1 2 3 4 5 |
sudo fdisk -l sudo fdisk /dev/sdc # input n, p ,1, enter, enter, w sudo mkfs.ext4 /dev/sdc1 sudo mkdir /mnt/SDReader sudo mount /dev/sdc1 /mnt/SDReader |
Download the root file system and some additional tegra drivers from Nvidia
1 2 3 4 5 6 7 |
wget http://developer.download.nvidia.com/embedded/L4T/r23_Release_v1.0/Tegra_Linux_Sample-Root-Filesystem_R23.1.1_armhf.tbz2 wget http://developer.download.nvidia.com/embedded/L4T/r23_Release_v1.0/Tegra210_Linux_R23.1.1_armhf.tbz2 sudo tar -pxvf Tegra210_Linux_R23.1.1_armhf.tbz2 cd Linux_for_Tegra/rootfs/ sudo tar xpfv ../../Tegra_Linux_Sample-Root-Filesystem_R23.1.1_armhf.tbz2 cd ../ sudo ./apply_binaries.sh |
Finally, to fix the wifi firmware, download https://drive.google.com/open?id=0Bz5kaPQJx_AgTjZBeGUycTBfa0E and extract to host ~. The in the vm
1 2 3 4 5 |
sudo mkdir -p ~/Linux_for_Tegra/rootfs/system/vendor/firmware/bcm4354/ sudo mv /vagrant/fw_bcmdhd.bin ~/Linux_for_Tegra/rootfs/system/vendor/firmware/bcm4354/ sudo mkdir -p ~/Linux_for_Tegra/rootfs/system/etc sudo mv /vagrant/nvram.txt ~/Linux_for_Tegra/rootfs/system/etc/nvram_rev.txt sudo sed -i -- 's/00:90:4c:16:70:01/00:04:4B:4B:72:1D/g' ~/Linux_for_Tegra/rootfs/system/etc/nvram_rev.txt |
Sync the prepared rootfs to the sdcard and unmount the disk:
1 2 |
sudo rsync -av ~/Linux_for_Tegra/rootfs/* /mnt/SDReader sudo umount /mnt/SDReader |
You can safely remove the micro sd card now and plug it into the back of your nvidia shield tv console.
2. Unlock the bootloader
First install the ADB tools for OS X
1 |
brew install android-platform-tools |
or Linux
1 |
sudo apt-get install android-tools-adb android-tools-fastboot |
Enable debugging on the Shield TV
1. Goto Settings
2. Go across to About in Device
3. Go down to Build and click on it 10x until it says you are in development mode
Enable ADB over USB
1. Make sure you have performed the above steps „Enable debugging“
2. Goto Settings
3. Go Across to Developer options
4. Go down to Debugging
5. Toggle USB debugging to On
Now boot into fastboot
– Perform software shutdown on SHIELD by holding Power button for 10 seconds
– Connect USB OTG cable to SHIELD
– Start pressing power button for 3 seconds
– HDMI TV should be always connected to SHIELD
You should now be able to see your shield from your computer by typing:
1 |
sudo adb devices |
if not, unplug the device, stop the adb server, add the nvidia vendor id to db_usb.ini and restart the server:
1 2 3 |
adb kill-server echo "0x0955" >> ~/.android/adb_usb.ini adb start-server |
plug the device back in and try add devices again.
Now get some information about the bootloader:
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 |
sudo fastboot getvar all < waiting for device > (bootloader) version-bootloader: 1.0 (bootloader) version-baseband: 2.0 (bootloader) version-mts: NO SUPPORT YET! (bootloader) version: 0.4 (bootloader) 042271508752300002d3 (bootloader) mid: 001 (bootloader) product: t210ref (bootloader) secure: Yes (bootloader) unlocked: No (bootloader) partition-size:bootloader: 0x0000000000200000 (bootloader) partition-type:bootloader: basic (bootloader) partition-size:recovery: 0x0000000001980000 (bootloader) partition-type:recovery: basic (bootloader) partition-size:boot: 0x0000000001980000 (bootloader) partition-type:boot: basic (bootloader) partition-size:dtb: 0x0000000000400000 (bootloader) partition-type:dtb: basic (bootloader) partition-size:system: 0x0000000080000000 (bootloader) partition-type:system: ext4 (bootloader) partition-size:cache: 0x0000000010000000 (bootloader) partition-type:cache: ext4 (bootloader) partition-size:userdata: 0x00000002d8e63e00 (bootloader) partition-type:userdata: ext4 all: finished. total time: 0.411s |
If your bootloader is locked, it must be unlocked first with:
1 2 3 4 5 6 7 8 9 10 |
sudo fastboot oem unlock ... (bootloader) erasing userdata... (bootloader) erasing userdata done (bootloader) erasing cache... (bootloader) erasing cache done (bootloader) Unlocking bootloader... (bootloader) Bootloader is unlocked now. OKAY [ 42.419s] finished. total time: 42.419s |
Select ‚Confirm‘ to unlock the bootloader which may take up to 2 hours for the pro device.
Now fastboot getvar all should read:
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 |
sudo fastboot getvar all < waiting for device > (bootloader) version-bootloader: 1.0 (bootloader) version-baseband: 2.0 (bootloader) version-mts: NO SUPPORT YET! (bootloader) version: 0.4 (bootloader) 042271508752300002d3 (bootloader) mid: 001 (bootloader) product: t210ref (bootloader) secure: No (bootloader) unlocked: Yes (bootloader) partition-size:bootloader: 0x0000000000200000 (bootloader) partition-type:bootloader: basic (bootloader) partition-size:recovery: 0x0000000001980000 (bootloader) partition-type:recovery: basic (bootloader) partition-size:boot: 0x0000000001980000 (bootloader) partition-type:boot: basic (bootloader) partition-size:dtb: 0x0000000000400000 (bootloader) partition-type:dtb: basic (bootloader) partition-size:system: 0x0000000080000000 (bootloader) partition-type:system: ext4 (bootloader) partition-size:cache: 0x0000000010000000 (bootloader) partition-type:cache: ext4 (bootloader) partition-size:userdata: 0x00000002d8e63e00 (bootloader) partition-type:userdata: ext4 all: finished. total time: 0.476s |
Now you have to setup Android TV again and activate debug mode again 🙁
Update:
Perform a downgrade to firmware 1.3, and root the shield while you are at it. With the current firmwares that is not necessary and recommended anymore. Firmware & bootloader updates always carry a inherent risk of bricking your device.
Register for Nvidia developer account, obtain and unzip the files, bring device into fast boot mode:
1 |
sudo ./update-all.sh |
3. To build a boot.img download the patched kernel source from GoogleDrive into your host machines vagrant dir. It should be auto mounted to /vagrant. Then extract the sources:
1 |
tar -xvzf /vagrant/cm-12.1.tar.gz -C ~ |
compile the kernel:
1 |
source cm-12.1/first.sh |
and finally make a bootable boot.mg
1 2 3 4 |
sudo apt-get install abootimg tar -xvzf /vagrant/initrd.tar.gz -C ~ cd ~/initrd make |
4. Put the sd card in Shield TV SD card slot, Plug OTG cable between Shield TV and PC go into fast boot mode
To boot Linux 4 Tegra once run from the VM:
1 |
sudo fastboot boot ~/cmOutDir1/boot.img |
The Nvidia Logo will pop up and go away while ubuntu starts, which may take a good 2 min. Log in with ubuntu/ubunu. If the Ubuntu desktop is too large for your tv screen, you may want to disable overscan in your tv’s settings.
Once that works, you may want to write boot.img into the recovery spot
1 |
sudo fastboot flash recovery ~/cmOutDir1/boot.img |
or even replace Android altogether by:
1 |
sudo fastboot flash boot ~/cmOutDir1/boot.img |
and then flash the original boot into the recovery spot. SSH into your shield
1 |
ssh ubuntu@ubuntu-tegra |
the password is ‚ubuntu‘.
Then first prevent the Nvidia driver for Tegra X1 being overwritten by apt-get upgrade by:
1 |
sudo apt-mark hold xserver.xorg.core |
Add yourself as a new user and copy your public key, install some frequently used packages:
1 2 3 4 5 6 7 8 9 10 11 |
sudo adduser tatsch sudo adduser tatsch sudo ssh-copy-id -i ~/.ssh/id_rsa.pub tatsch@shieldtv sudo apt-get install language-pack-de-base sudo apt-get update && sudo apt-get upgrade sudo apt-get install zsh git nano sudo wget https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | zsh chsh -s `which zsh` sed -i 's/robbyrussell/af-magic/g' ~/.zshrc zsh |
Now lets install the CUDA support. Download https://developer.nvidia.com/embedded/jetson-development-pack and apt-get sources and scp them to your shield.
1 2 3 4 5 6 7 8 |
scp cuda-repo-l4t-r23.1-7-0-local_7.0-71_armhf.deb shieldtv:~/ scp JetPack-L4T-2.0-linux-x64.run shieldtv:~/ sudo dpkg -i cuda-repo-l4t-r23.1-7-0-local_7.0-71_armhf.deb sudo apt-get update chmod +x JetPack-L4T-2.0-linux-x64.run ./JetPack-L4T-2.0-linux-x64.run cd _installer ./cuda-l4t.sh ../cuda-repo-l4t-r23.1-7-0-local_7.0-71_armhf.deb 7.0 7-0 |
Finally add the CUDA stuff to the path:
1 2 3 |
echo "export PATH=/usr/local/cuda-7.0/bin:$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" >> ~/.zshrc echo "export LD_LIBRARY_PATH=/usr/local/cuda-7.0/lib:" >> ~/.zshrc source ~/.zshrc |
Now you should be able to call the CUDA compiler:
1 |
nvcc -V |
Next, tune the shield to achieve the full performance:
1 2 3 |
wget https://gist.githubusercontent.com/jmtatsch/8c360bb0ca3990d78f75/raw -O maxPerf.sh chmod +x maxPerf.sh sudo ./maxPerf.sh |
Now you can try out some of the examples in
1 2 3 4 |
cd /usr/local/cuda-7.0/samples/5_Simulations/ cd nbody sudo make ./nbody -benchmark -numbodies=65536 |