Project

General

Profile

Flashing » History » Revision 6

Revision 5 (xilokar, 05/06/2022 08:17 PM) → Revision 6/8 (xilokar, 05/06/2022 08:23 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> 
 
 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>
Add picture from clipboard (Maximum size: 48.8 MB)