Flashing » History » Revision 5

« Previous | Revision 5/8 (diff) | Next »
xilokar, 05/06/2022 08:17 PM


There are several way to flash partitions (e.g. updating) manually:
  • using /usr/sbin/ubiupdatevol:
    ubiupdatevol version 1.2 - a tool to write data to UBI volumes.
    Usage: ubiupdatevol <UBI volume node file name> [-t] [-s <size>] [-h] [-V] [--truncate]
                [--size=<size>] [--help] [--version] <image file>
    Example 1: ubiupdatevol /dev/ubi0_1 fs.img - write file "fs.img" to UBI volume /dev/ubi0_1
    Example 2: ubiupdatevol /dev/ubi0_1 -t - wipe out UBI volume /dev/ubi0_1
    -t, --truncate             truncate volume (wipe it out)
    -s, --size=<bytes>         bytes in input, if not reading from file
    -h, --help                 print help message
    -V, --version              print program version
  • using /APP/dev_only/ - update flash partitions on the target
    Easy mode:
       using NFS: -i<IP> -p<PATH>
       <IP>   = IP address of your VM (defaults to
       <PATH> = path of NFS directory (defaults to /home/femto/ftpdata)
       using wget: -w<URL>
       <URL>  = URL to fetch images from (e.g. ftp://user:pass@host/path)
    Expert mode: (stay away from them!)
       -k update kernel
       -r update root fs
       -a update application partition
       -u update unitdata partition
       -c update caldata partition
       -x toggle banks
       -z don't reboot after successful update
       -o<str> Pass option string <str> to wget

/etc/init.d/flash_update takes care of flashing all partitions at once (also done during boot in /etc/init.d/rcS).

Lastly the operator can also flash images remotely through /APP/bin/oam_start.

Secure boot


The partition signatures (kernel, rootfs, data) are stored in /dev/mtdblock2/bootdata.ini (the only file in the bootdata partition).
While bootdata is not signed itself, it only contains the signatures.
You can also see the content using /APP/dev_only/
The corresponding public key seems to be burned in the OTP section of the CPU, providing secure boot (this has not been verified).

bootdata.ini also defines which system will be booted (A or B).
The file is updated using /APP/dev_only/

For the Bootlog the femtocell seems to use "secure boot":
  1. the Percello bootrom verifies the Percello bootloader:
    Percello bootrom version 1.2.8
    Board: Secure mode
    Secured device - OTP2: verification ...PASSED
    Secured device - OTP3: verification ...PASSED
    Running Percello bootloader
  2. the Percello bootloader loader the Sagemcom FM-loader
    Nand execute: load_addr: 3fe0000
    Percello bootloader version 0.6 (from NAND)
  3. the Sagemcom FM-loader verifies the signatures of the kernel, rootfs, and app partitions
    Sagemcom FM-loader v2.0.4-11
    Boot 1 (cold) into main system, secured
    Unit key found and verified
    TrustStor signature check passed
    Group A signature check passed
    Kernel A signature check passed
    Root file system A signature check passed
    Application file system A signature check passed

You can check if secure boot has been activated using cat /proc/prc6000/otp_data/boot/secured but it is unclear how the signatures are verified.

Unlocking bootloader

Do this at your own risk

First grab a copy of the current bootloader

# dd if=/dev/mtdblock0 of=/tmp/boot.bin

Following instructions/patches are valid for this bootloader:
$ md5sum boot.bin 
ae00a5f7dab5ab8f82c4d7ba5169d713  boot.bin

extract header and first stage
$ dd if=boot.bin bs=1  count=$((0x5500)) of=percello.bin

patch it
bspatch percello.bin percello-patched.bin percello.bspatch

extract fm-loader
$ dd if=boot.bin bs=1 skip=$((0x5508))  count=$((0x85af)) of=fm.bin.gz
$ gunzip fm.bin.gz

patch fm.bin
$ bspatch fm.bin fm-patched.bin fm.bspatch

$ gzip fm-patched.bin

get the size of fm-patched.bin.gz
write fm-header
$ echo "00 00 00 00 xx xx xx xx" | xxd -r -p > fm-block.bin

where xx xx xx xx being the hex size of fm-patched.bin.gz, little endian

append fm-patched.bin.gz

$ cat fm-patched.bin.gz >> fm-block.bin

pack header, first stage and fm
$ cat fm-patched.bin fm-block.bin > patched-bootloader.bin

pad it to 0x1c000 where we will put the stack smasher signature
$ truncate -s $((0x1c000)) patched-bootloader.bin

append stack-smasher
$ cat stacksmash-padded.bin >> patched-bootloader.bin

The resulting binary size should be 128k

write the patched bootloader

# dd if=patched-bootloader.bin of=/dev/mtdblock0


The unidata (mtd3) signature is checked in /etc/init.d/flash_update (called by /etc/init.d/rcS) using /boot/bc_cli -u${PARTNUM_UNITDATA} -q (with PARTNUM_UNITDATA=3):
  • hash is sha1sum of 0x2000 (8192) first bytes
  • signature is at 0x2000 (after the cramfs indicated size)
  • public key is first 256 bytes of /caldata/unitkey.bin

It the signature check fails, unidata_backup is used.
If this signature check fails too, it enters recovery mode

caldata in mounted without check (in /etc/init.d/flash_update).
This allows to flash your own operator data:
  1. create your own key pair
    # generate 2048-bit RSA key pair
    openssl genrsa -out key.pem 2048
    # export public key
    openssl rsa -in key.pem -pubout -out pubkey.pem
    # export public key as raw bytes
    openssl rsa -in key.pem -pubout -text 2>&1 | grep -A18 "modulus" | tail -n +2 | sed "s/[^0-9a-f]//g" | sed "s/^00//" | xxd -r -p > pubkey.bin
  2. prepare the unitdata
    # create cramfs image
    mkfs.cramfs unitdata_folder unitdata.bin
    # sign partition
    openssl dgst -sha1 -sign key.pem -out unitdata.sig unitdata.bin
    # verify signature
    openssl dgst -sha1 -verify pubkey.pem -signature unitdata.sig unitdata.bin
    # append signature to image (read out by bc_cli)
    cat unitdata.sig >> unitdata.bin
  3. transfer data
    # transfer unidata image
    scp -i /tmp/femto_id_rsa -o KexAlgorithms=diffie-hellman-group1-sha1 unitdata.bin root@
    # transfer public key
    scp -i /tmp/femto_id_rsa -o KexAlgorithms=diffie-hellman-group1-sha1 pubkey.bin root@
  4. install images on femtocell (once logged in as root)
    # copy original caldata files
    cp -r /caldata /tmp/caldata
    # backup original keys (only do this the first time you flash caldata)
    mv /tmp/caldata/unitkey.bin /tmp/caldata/unitkey.bin.bak
    # write public key to unitkey.bin (used by bc_cli to verify unitdata partition)
    cp /tmp/pubkey.bin /tmp/caldata/unitkey.bin
    # append rest of data (not sure what it is used for)
    dd if=/tmp/caldata/unitkey.bin.bak bs=1 skip=256 >> /tmp/caldata/unitkey.bin
    # create caldata cramfs image
    mkfs.cramfs /tmp/caldata /tmp/caldata.bin
    # flash new caldata image
    umount /caldata
    source /etc/init.d/
    ubiupdatevol /dev/ubi0_$(($PARTNUM_CALDATA-$PARTNUM_UBI_OFFS)) /tmp/caldata.bin
    # flash new unitdata image
    umount /unitdata
    ubiupdatevol /dev/ubi0_$(($PARTNUM_UNITDATA-$PARTNUM_UBI_OFFS)) /tmp/unitdata.bin
    # enjoy
Files (3)
fm.bspatch fm.bspatch 230 Bytes xilokar, 05/06/2022 08:00 PM
stacksmash-padded.bin stacksmash-padded.bin 16 KB xilokar, 05/06/2022 08:00 PM
percello.bspatch percello.bspatch 161 Bytes xilokar, 05/06/2022 08:00 PM

Updated by xilokar almost 2 years ago · 5 revisions

Add picture from clipboard (Maximum size: 48.8 MB)