Flashing » History » Version 6
xilokar, 05/06/2022 08:23 PM
1 | 1 | tsaitgaist | h1. Flashing |
---|---|---|---|
2 | |||
3 | There are several way to flash partitions (e.g. updating) manually: |
||
4 | * using @/usr/sbin/ubiupdatevol@: |
||
5 | <pre> |
||
6 | ubiupdatevol version 1.2 - a tool to write data to UBI volumes. |
||
7 | |||
8 | Usage: ubiupdatevol <UBI volume node file name> [-t] [-s <size>] [-h] [-V] [--truncate] |
||
9 | [--size=<size>] [--help] [--version] <image file> |
||
10 | |||
11 | Example 1: ubiupdatevol /dev/ubi0_1 fs.img - write file "fs.img" to UBI volume /dev/ubi0_1 |
||
12 | Example 2: ubiupdatevol /dev/ubi0_1 -t - wipe out UBI volume /dev/ubi0_1 |
||
13 | |||
14 | -t, --truncate truncate volume (wipe it out) |
||
15 | -s, --size=<bytes> bytes in input, if not reading from file |
||
16 | -h, --help print help message |
||
17 | -V, --version print program version |
||
18 | </pre> |
||
19 | * using @/APP/dev_only/swupd.sh@ |
||
20 | <pre> |
||
21 | swupd.sh - update flash partitions on the target |
||
22 | |||
23 | Easy mode: |
||
24 | using NFS: swupd.sh -i<IP> -p<PATH> |
||
25 | where: |
||
26 | <IP> = IP address of your VM (defaults to 192.168.16.18) |
||
27 | <PATH> = path of NFS directory (defaults to /home/femto/ftpdata) |
||
28 | |||
29 | using wget: swupd.sh -w<URL> |
||
30 | where: |
||
31 | <URL> = URL to fetch images from (e.g. ftp://user:pass@host/path) |
||
32 | |||
33 | Expert mode: (stay away from them!) |
||
34 | -k update kernel |
||
35 | -r update root fs |
||
36 | -a update application partition |
||
37 | -u update unitdata partition |
||
38 | -c update caldata partition |
||
39 | -x toggle banks |
||
40 | -z don't reboot after successful update |
||
41 | |||
42 | -o<str> Pass option string <str> to wget |
||
43 | </pre> |
||
44 | |||
45 | 2 | tsaitgaist | @/etc/init.d/flash_update@ takes care of flashing all partitions at once (also done during boot in @/etc/init.d/rcS@). |
46 | 1 | tsaitgaist | |
47 | Lastly the operator can also flash images remotely through @/APP/bin/oam_start@. |
||
48 | 2 | tsaitgaist | |
49 | h1. Secure boot |
||
50 | |||
51 | h2. System |
||
52 | |||
53 | The partition signatures (kernel, rootfs, data) are stored in @/dev/mtdblock2/bootdata.ini@ (the only file in the @bootdata@ partition). |
||
54 | While @bootdata@ is not signed itself, it only contains the signatures. |
||
55 | You can also see the content using @/APP/dev_only/cat_bootdata.sh@ |
||
56 | The corresponding public key seems to be burned in the OTP section of the CPU, providing secure boot (this has not been verified). |
||
57 | 1 | tsaitgaist | |
58 | @bootdata.ini@ also defines which system will be booted (A or B). |
||
59 | The file is updated using @/APP/dev_only/write_bootdata.sh@ |
||
60 | 3 | tsaitgaist | |
61 | For the [[Bootlog]] the femtocell seems to use "secure boot": |
||
62 | # the Percello bootrom verifies the Percello bootloader: |
||
63 | <pre> |
||
64 | Percello bootrom version 1.2.8 |
||
65 | ... |
||
66 | Board: Secure mode |
||
67 | ... |
||
68 | Secured device - OTP2: verification ...PASSED |
||
69 | Secured device - OTP3: verification ...PASSED |
||
70 | Running Percello bootloader |
||
71 | PASSED |
||
72 | </pre> |
||
73 | # the Percello bootloader loader the Sagemcom FM-loader |
||
74 | <pre> |
||
75 | Nand execute: load_addr: 3fe0000 |
||
76 | |||
77 | Percello bootloader version 0.6 (from NAND) |
||
78 | </pre> |
||
79 | # the Sagemcom FM-loader verifies the signatures of the kernel, rootfs, and app partitions |
||
80 | <pre> |
||
81 | Sagemcom FM-loader v2.0.4-11 |
||
82 | Boot 1 (cold) into main system, secured |
||
83 | ... |
||
84 | Unit key found and verified |
||
85 | TrustStor signature check passed |
||
86 | Group A signature check passed |
||
87 | Kernel A signature check passed |
||
88 | Root file system A signature check passed |
||
89 | Application file system A signature check passed |
||
90 | </pre> |
||
91 | |||
92 | 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. |
||
93 | 2 | tsaitgaist | |
94 | 5 | xilokar | h2. Unlocking bootloader |
95 | |||
96 | *Do this at your own risk* |
||
97 | |||
98 | First grab a copy of the current bootloader |
||
99 | <pre> |
||
100 | # dd if=/dev/mtdblock0 of=/tmp/boot.bin |
||
101 | </pre> |
||
102 | Following instructions/patches are valid for this bootloader: |
||
103 | <pre> |
||
104 | $ md5sum boot.bin |
||
105 | ae00a5f7dab5ab8f82c4d7ba5169d713 boot.bin |
||
106 | </pre> |
||
107 | extract header and first stage |
||
108 | <pre> |
||
109 | $ dd if=boot.bin bs=1 count=$((0x5500)) of=percello.bin |
||
110 | </pre> |
||
111 | 6 | xilokar | patch it with attachment:percello.bspatch |
112 | 5 | xilokar | <pre> |
113 | bspatch percello.bin percello-patched.bin percello.bspatch |
||
114 | </pre> |
||
115 | extract fm-loader |
||
116 | <pre> |
||
117 | $ dd if=boot.bin bs=1 skip=$((0x5508)) count=$((0x85af)) of=fm.bin.gz |
||
118 | $ gunzip fm.bin.gz |
||
119 | </pre> |
||
120 | 6 | xilokar | patch fm.bin with attachment:fm.bspatch |
121 | 5 | xilokar | <pre> |
122 | $ bspatch fm.bin fm-patched.bin fm.bspatch |
||
123 | </pre> |
||
124 | Then |
||
125 | <pre> |
||
126 | $ gzip fm-patched.bin |
||
127 | </pre> |
||
128 | get the size of fm-patched.bin.gz |
||
129 | write fm-header |
||
130 | <pre> |
||
131 | $ echo "00 00 00 00 xx xx xx xx" | xxd -r -p > fm-block.bin |
||
132 | </pre> |
||
133 | where xx xx xx xx being the hex size of fm-patched.bin.gz, little endian |
||
134 | |||
135 | append fm-patched.bin.gz |
||
136 | <pre> |
||
137 | $ cat fm-patched.bin.gz >> fm-block.bin |
||
138 | </pre> |
||
139 | pack header, first stage and fm |
||
140 | <pre> |
||
141 | $ cat fm-patched.bin fm-block.bin > patched-bootloader.bin |
||
142 | </pre> |
||
143 | pad it to 0x1c000 where we will put the stack smasher signature |
||
144 | <pre> |
||
145 | $ truncate -s $((0x1c000)) patched-bootloader.bin |
||
146 | </pre> |
||
147 | 6 | xilokar | append stack-smasher attachment:stacksmash-padded.bin |
148 | 5 | xilokar | <pre> |
149 | $ cat stacksmash-padded.bin >> patched-bootloader.bin |
||
150 | </pre> |
||
151 | The resulting binary size should be 128k |
||
152 | |||
153 | write the patched bootloader |
||
154 | <pre> |
||
155 | # dd if=patched-bootloader.bin of=/dev/mtdblock0 |
||
156 | </pre> |
||
157 | |||
158 | 2 | tsaitgaist | h2. Operator |
159 | |||
160 | 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): |
||
161 | * hash is sha1sum of 0x2000 (8192) first bytes |
||
162 | * signature is at 0x2000 (after the cramfs indicated size) |
||
163 | * public key is first 256 bytes of @/caldata/unitkey.bin@ |
||
164 | |||
165 | It the signature check fails, @unidata_backup@ is used. |
||
166 | If this signature check fails too, it enters recovery mode |
||
167 | |||
168 | 4 | tsaitgaist | @caldata@ in mounted without check (in @/etc/init.d/flash_update@). |
169 | This allows to flash your own operator data: |
||
170 | # create your own key pair |
||
171 | <pre> |
||
172 | # generate 2048-bit RSA key pair |
||
173 | openssl genrsa -out key.pem 2048 |
||
174 | # export public key |
||
175 | openssl rsa -in key.pem -pubout -out pubkey.pem |
||
176 | # export public key as raw bytes |
||
177 | 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 |
||
178 | </pre> |
||
179 | # prepare the @unitdata@ |
||
180 | <pre> |
||
181 | # create cramfs image |
||
182 | mkfs.cramfs unitdata_folder unitdata.bin |
||
183 | # sign partition |
||
184 | openssl dgst -sha1 -sign key.pem -out unitdata.sig unitdata.bin |
||
185 | # verify signature |
||
186 | openssl dgst -sha1 -verify pubkey.pem -signature unitdata.sig unitdata.bin |
||
187 | # append signature to image (read out by bc_cli) |
||
188 | cat unitdata.sig >> unitdata.bin |
||
189 | </pre> |
||
190 | # transfer data |
||
191 | <pre> |
||
192 | # transfer unidata image |
||
193 | scp -i /tmp/femto_id_rsa -o KexAlgorithms=diffie-hellman-group1-sha1 unitdata.bin root@192.168.23.200:/tmp/ |
||
194 | # transfer public key |
||
195 | scp -i /tmp/femto_id_rsa -o KexAlgorithms=diffie-hellman-group1-sha1 pubkey.bin root@192.168.23.200:/tmp/ |
||
196 | </pre> |
||
197 | # install images on femtocell (once logged in as root) |
||
198 | <pre> |
||
199 | # copy original caldata files |
||
200 | cp -r /caldata /tmp/caldata |
||
201 | # backup original keys (only do this the first time you flash caldata) |
||
202 | mv /tmp/caldata/unitkey.bin /tmp/caldata/unitkey.bin.bak |
||
203 | # write public key to unitkey.bin (used by bc_cli to verify unitdata partition) |
||
204 | cp /tmp/pubkey.bin /tmp/caldata/unitkey.bin |
||
205 | # append rest of data (not sure what it is used for) |
||
206 | dd if=/tmp/caldata/unitkey.bin.bak bs=1 skip=256 >> /tmp/caldata/unitkey.bin |
||
207 | # create caldata cramfs image |
||
208 | mkfs.cramfs /tmp/caldata /tmp/caldata.bin |
||
209 | # flash new caldata image |
||
210 | umount /caldata |
||
211 | source /etc/init.d/partnum.sh |
||
212 | ubiupdatevol /dev/ubi0_$(($PARTNUM_CALDATA-$PARTNUM_UBI_OFFS)) /tmp/caldata.bin |
||
213 | sync |
||
214 | # flash new unitdata image |
||
215 | umount /unitdata |
||
216 | ubiupdatevol /dev/ubi0_$(($PARTNUM_UNITDATA-$PARTNUM_UBI_OFFS)) /tmp/unitdata.bin |
||
217 | sync |
||
218 | # enjoy |
||
219 | reboot |
||
220 | </pre> |