Flashing » History » Revision 7
Revision 6 (xilokar, 05/06/2022 08:23 PM) → Revision 7/8 (xilokar, 05/06/2022 08:37 PM)
h1. Flashing There are several way to flash partitions (e.g. updating) manually: * using @/usr/sbin/ubiupdatevol@: <pre> 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 </pre> * using @/APP/dev_only/swupd.sh@ <pre> swupd.sh - update flash partitions on the target Easy mode: using NFS: swupd.sh -i<IP> -p<PATH> where: <IP> = IP address of your VM (defaults to 192.168.16.18) <PATH> = path of NFS directory (defaults to /home/femto/ftpdata) using wget: swupd.sh -w<URL> where: <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 </pre> @/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@. h1. Secure boot h2. System 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/cat_bootdata.sh@ 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/write_bootdata.sh@ For the [[Bootlog]] the femtocell seems to use "secure boot": # the Percello bootrom verifies the Percello bootloader: <pre> Percello bootrom version 1.2.8 ... Board: Secure mode ... Secured device - OTP2: verification ...PASSED Secured device - OTP3: verification ...PASSED Running Percello bootloader PASSED </pre> # the Percello bootloader loader the Sagemcom FM-loader <pre> Nand execute: load_addr: 3fe0000 Percello bootloader version 0.6 (from NAND) </pre> # the Sagemcom FM-loader verifies the signatures of the kernel, rootfs, and app partitions <pre> 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 </pre> 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. h2. Unlocking bootloader *Do this at your own risk* First grab a copy of the current bootloader <pre> # dd if=/dev/mtdblock0 of=/tmp/boot.bin </pre> Following instructions/patches are valid for this bootloader: <pre> $ md5sum boot.bin ae00a5f7dab5ab8f82c4d7ba5169d713 boot.bin </pre> extract header and first stage <pre> $ dd if=boot.bin bs=1 count=$((0x5500)) of=percello.bin </pre> patch it with attachment:percello.bspatch <pre> bspatch percello.bin percello-patched.bin percello.bspatch </pre> extract fm-loader <pre> $ dd if=boot.bin bs=1 skip=$((0x5508)) count=$((0x85af)) of=fm.bin.gz $ gunzip fm.bin.gz </pre> patch fm.bin with attachment:fm.bspatch <pre> $ bspatch fm.bin fm-patched.bin fm.bspatch </pre> Then <pre> $ gzip fm-patched.bin </pre> get the size of fm-patched.bin.gz write fm-header <pre> $ echo "00 00 00 00 xx xx xx xx" | xxd -r -p > fm-block.bin </pre> where xx xx xx xx being the hex size of fm-patched.bin.gz, little endian append fm-patched.bin.gz <pre> $ cat fm-patched.bin.gz >> fm-block.bin </pre> pack header, first stage and fm <pre> $ cat fm-patched.bin fm-block.bin > patched-bootloader.bin </pre> pad it to 0x1c000 where we will put the stack smasher signature <pre> $ truncate -s $((0x1c000)) patched-bootloader.bin </pre> append stack-smasher attachment:stacksmash-padded.bin <pre> $ cat stacksmash-padded.bin >> patched-bootloader.bin </pre> The resulting binary size should be 128k write the patched bootloader <pre> # dd if=patched-bootloader.bin of=/dev/mtdblock0 </pre> h3. tune your firmware grab the kernel, rootfs and app paritions in use. tune rootfs and app <pre> fakeroot fsck.crmafs --extract=dir # patch (eg: remove firewall, change shadow...) mkfs.cramfs dir out.img </pre> and flash it: put it on a web server with this filenames: <pre> $ ls femtoplug appA.img, rfsA.img, uImageA </pre> and update it <pre> /APP/dev_only/swupd.sh -k -r -a -w http://xx.xx.xx.xx/femtoplug -z -x </pre> h2. Operator 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: # create your own key pair <pre> # 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 </pre> # prepare the @unitdata@ <pre> # 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 </pre> # transfer data <pre> # transfer unidata image scp -i /tmp/femto_id_rsa -o KexAlgorithms=diffie-hellman-group1-sha1 unitdata.bin root@192.168.23.200:/tmp/ # transfer public key scp -i /tmp/femto_id_rsa -o KexAlgorithms=diffie-hellman-group1-sha1 pubkey.bin root@192.168.23.200:/tmp/ </pre> # install images on femtocell (once logged in as root) <pre> # 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/partnum.sh ubiupdatevol /dev/ubi0_$(($PARTNUM_CALDATA-$PARTNUM_UBI_OFFS)) /tmp/caldata.bin sync # flash new unitdata image umount /unitdata ubiupdatevol /dev/ubi0_$(($PARTNUM_UNITDATA-$PARTNUM_UBI_OFFS)) /tmp/unitdata.bin sync # enjoy reboot </pre>