Agptek Rocker: Add tools to work with OF update images

Original firmware update is provided as .upt file. This file
is actually ISO9660 image containing uBoot, kernel image and
UBIFS rootfs and additional control files. Installing
bootloader means patching UBIFS rootfs image.

Change-Id: Ica86d1189dc1d5f3131d2035d8b87c8d08ec36b5
This commit is contained in:
Marcin Bukat 2018-02-26 13:47:29 +01:00
parent d55680993d
commit 09fde79ec8
5 changed files with 316 additions and 0 deletions

View file

@ -0,0 +1,50 @@
FROM debian:9
WORKDIR /home/rb
ENV HOME /home/rb
# Install tools needed
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y \
build-essential \
git \
perl \
curl \
texinfo \
flex \
bison \
bzip2 \
gzip \
zip \
patch \
automake \
libtool \
libtool-bin \
autoconf \
libmpc-dev \
gawk \
python \
python-lzo \
python-setuptools \
mtd-utils \
xorriso && \
rm -rf /var/lib/apt/lists/*
# Clone rockbox repository
RUN cd /home/rb && \
git clone https://github.com/wodz/rockbox-wodz.git
# Build cross toolchain (It takes quite long)
RUN cd /home/rb/rockbox-wodz && \
git checkout agptek-rocker && \
./tools/rockboxdev.sh --target=y
# Install tools for unpacking ubifs
RUN cd /home/rb && \
git clone https://github.com/jrspruitt/ubi_reader.git && \
cd /home/rb/ubi_reader && \
python setup.py install
# Copy build script
RUN cp /home/rb/rockbox-wodz/tools/agptek_rocker/bootloader_install.sh /usr/local/bin && \
chmod 755 /usr/local/bin/bootloader_install.sh

View file

@ -0,0 +1,46 @@
Steps needed to patch update.upt with rockbox bootloader are explained in
bootloader_install.sh shell script. Process is quite involved and some
custom tools are needed.
For convenience Dockerfile is provided which prepares custom image based
on debian 9 which has all the tools needed to work with Agptek Rocker update
images.
Basically image extends standard debian image by:
1) Installing developer packages from stock debian
2) Cloning https://github.com/wodz/rockbox-wodz.git
3) Building custom cross toolchain
4) Cloning and installing tools to work with UBIFS
You first need to build image with:
docker build . -t "agptek-dev"
Then you can start container and work with update.upt.
If you want to generate patched update image in automatic way:
docker run --rm -it -v /path/to/dir/with/update.upt:/upt \
-e UPT_DIR=/upt agptek-dev bootloader_install.sh
Patched update.upt with rockbox bootloader and rockbox.zip should end up in
specified directory.
If you want to play around, hack something etc. you can run container in
interactive mode:
docker run -it -v /path/to/dir/with/update.upt:/upt \
-e UPT_DIR=/upt agptek-dev bash
Files in this directory:
README - this file
bootloader_install.sh - shell script documenting process of patching
agptek rocker update images
update_update.py - little helper utility to patch update.txt
controll file
hiby_player.sh - shell script called on player boot which
originally started music player application
and now it starts bootloader
Dockerfile - file to build docker image with all needed
tools to play with agptek rocker files

View file

@ -0,0 +1,129 @@
#!/bin/sh
[ -z "$UPT_DIR" ] && UPT_DIR=`pwd`
cd $HOME
# get sources
echo
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "!!! STEP 0: Get sources !!!"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo
[ -d "$HOME/rockbox-wodz" ] || git clone https://github.com/wodz/rockbox-wodz.git
cd $HOME/rockbox-wodz
# build bootloader
echo
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "!!! STEP 1: Build bootloader !!!"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo
[ -d "$HOME/rockbox-wodz/build" ] && rm -rf $HOME/rockbox-wodz/build
git checkout agptek-rocker && \
git pull && \
mkdir $HOME/rockbox-wodz/build && cd $HOME/rockbox-wodz/build && \
../tools/configure --target=240 --type=b && \
make clean && \
make && \
cd $HOME
# Extract update file (ISO9660 image) content
# NOTE: Update process on device loop mount ISO image. Default behavior of mount
# is to map all names to lowercase. Because of this forcing lowercase
# mapping is needed when extracting
echo
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "!!! STEP 2: Extract upt file !!!"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo
[ -d "$HOME/iso" ] && rm -rf $HOME/iso
mkdir $HOME/iso && \
xorriso -osirrox on -ecma119_map lowercase -indev $UPT_DIR/update.upt -extract / $HOME/iso
# Extract rootfs files. Preserve permissions (although this are wrong!)
echo
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "!!! STEP 3: Extract system.ubi !!!"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo
ubireader_extract_files -k -o $HOME/rootfs $HOME/iso/system.ubi
# Copy rockbox bootloader
echo
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "!!! STEP 4: Copy bootloader !!!"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo
cp $HOME/rockbox-wodz/build/bootloader.elf $HOME/rootfs/usr/bin/rb_bootloader && \
mipsel-rockbox-linux-gnu-strip --strip-unneeded $HOME/rootfs/usr/bin/rb_bootloader
# Overwrite default player starting script with one running our bootloader
echo
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "!!! STEP 5: Modify startup script !!!"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo
cp $HOME/rockbox-wodz/tools/agptek_rocker//hiby_player.sh $HOME/rootfs/usr/bin/hiby_player.sh && \
chmod 755 $HOME/rootfs/usr/bin/hiby_player.sh
# Rebuild ubifs
echo
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "!!! STEP 6: Rebuild system.ubi !!!"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo
mkfs.ubifs --min-io-size=2048 --leb-size=126976 --max-leb-cnt=1024 -o $HOME/system_rb.ubi -r $HOME/rootfs && \
mv $HOME/system_rb.ubi $HOME/iso/system.ubi
# Fixup update.txt file with correct md5
echo
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "!!! STEP 7: Fixup update.txt !!!"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo
python $HOME/rockbox-wodz/tools/agptek_rocker/update_update.py $HOME/iso/update.txt
# Rebuild .upt file
echo
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "!!! STEP 8: Rebuild upt file !!!"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo
xorriso -as mkisofs -volid 'CDROM' --norock -output $UPT_DIR/update_rb.upt $HOME/iso
# Build rockbox.zip
echo
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "!!! STEP 9: Build rockbox application !!!"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo
cd $HOME/rockbox-wodz/build && \
../tools/configure --target=240 --type=n && \
make clean && \
make && \
make zip && \
cp rockbox.zip $UPT_DIR/
# Cleanup
echo
echo "!!!!!!!!!!!!!!!!!!!!!!!!"
echo "!!! STEP 10: Cleanup !!!"
echo "!!!!!!!!!!!!!!!!!!!!!!!!"
echo
rm -rf $HOME/rockbox-wodz/build
rm -rf $HOME/iso
rm -rf $HOME/rootfs
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "! Building finished !"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo
echo "You should find update_rb.upt and rockbox.zip in output directory"
echo
echo "1) Unzip rockbox.zip file in the root directory of SD card"
echo "2) Copy update_rb.upt to the root directory of SD card"
echo "3) Rename update_rb.upt to update.upt in SD card"
echo "4) Select update firmware on device"
echo

View file

@ -0,0 +1,10 @@
#!/bin/sh
mount /dev/mmcblk0 /mnt/sd_0 &>/dev/null || \
mount /dev/mmcblk0p1 /mnt/sd_0 &>/dev/null
killall rb_bootloader &>/dev/null
killall -9 rb_bootloader &>/dev/null
/usr/bin/rb_bootloader
sleep 1

View file

@ -0,0 +1,81 @@
#!/usr/bin/env python
import os
import sys
import hashlib
import argparse
from collections import OrderedDict
EQ = '='
BLK_START = '{'
BLK_END = '}'
#name: {key: value, key: value}
def parse(filename):
blocks = OrderedDict()
blk = None
key = None
value = None
with open(filename) as f:
# read all lines
for line in f:
# if line has '=' sign treat it
# as split symbol
if EQ in line:
key, value = line.split(EQ, 1)
key = key.strip()
value = value.strip()
if value == BLK_START:
# value on the right of '=' is '{'
# so this opens new block
blk = key
blocks[key] = OrderedDict()
elif value == BLK_END:
# value on the right of '=' is '}'
# this terminates block
blk = None
else:
# key = value inside block
blocks[blk][key] = value
# return parsed structure as dictionary
return blocks
# write back internal representation into file
def dump(tree, filename=None):
with open(filename, 'w') as f:
for blk in tree.keys():
f.write('\n%s={\n' % blk)
for key,value in tree[blk].items():
f.write('\t%s=%s\n' % (key,value))
f.write('}\n')
if __name__=='__main__':
description = 'Update information in update.txt control file.'
usage = 'update_update.py filepath'
argp = argparse.ArgumentParser(usage=usage, description=description)
argp.add_argument('filepath', help='update.txt filepath to update contents of.')
if len(sys.argv) == 1:
argp.print_help()
sys.exit(1)
args = argp.parse_args()
# build config file representation
tree = parse(args.filepath)
dir = os.path.dirname(args.filepath)
# update all md5 sums
for blk in tree.keys():
filename = os.path.join(dir, os.path.basename(tree[blk]['file_path']))
with open(filename) as f:
tree[blk]['md5'] = hashlib.md5(f.read()).hexdigest()
# write back result
dump(tree, args.filepath)