Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/bin/sh | |
| 2 # | |
| 3 # Copyright (C) 2010 Google Inc. | |
| 4 # Written by David Hendricks for Google Inc. | |
| 5 # | |
| 6 # This program is free software; you can redistribute it and/or modify | |
| 7 # it under the terms of the GNU General Public License as published by | |
| 8 # the Free Software Foundation; either version 2 of the License, or | |
| 9 # (at your option) any later version. | |
| 10 # | |
| 11 # This program is distributed in the hope that it will be useful, | |
| 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 # GNU General Public License for more details. | |
| 15 # | |
| 16 # You should have received a copy of the GNU General Public License | |
| 17 # along with this program; if not, write to the Free Software | |
| 18 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
| 19 # | |
| 20 # ec.sh: This will attempt to stress partial write capabilities for EC firmware | |
| 21 # ROMs. There are two major parts to the test: | |
| 22 # 1. Write an alternative firmware image to the "fw" region specified in a | |
| 23 # layout file. | |
| 24 # 2. Stress partial writes using a known pattern in an unused region of the | |
| 25 # EC firmware ROM with 128KB of space. | |
| 26 # | |
| 27 # REQUIRED ENVIRONMENT VARIABLES | |
| 28 # ------------------------------ | |
| 29 # Due to the way the test framework copies tests, the environment variables must | |
| 30 # specify absolute paths to files they reference. | |
| 31 # | |
| 32 # $ALT_EC_IMAGE -- Required environment variable | |
| 33 # This script requires an alternative EC firmware. Most ECs actively read code | |
| 34 # and data from the firmware ROM during run-time. An example of an EC firmware | |
| 35 # update process for supported ECs: | |
| 36 # 1. Enter update mode -- Copy relevant code and data to internal RAM | |
| 37 # 2. Enable programming interface | |
| 38 # 3. When host is done programming ROM, issue "exit update mode" | |
| 39 # 4. Re-load code/data from ROM. | |
| 40 # | |
| 41 # Step 4 can cause failure if we attempt to test using patterns. Instead, we | |
| 42 # must provide the EC with usable code. For blackbox testing, this essentially | |
| 43 # means replacing the current firmware image with a different image which still | |
| 44 # works. | |
| 45 # | |
| 46 # $LAYOUT_FILE -- Another required environment variable | |
| 47 # A layout file is required for two reasons: | |
| 48 # 1. We need a way of knowing which regions are safe to leave in a clobbered | |
| 49 # state after exiting flash update mode. They will be labeled "unused". | |
| 50 # 2. We need a way of knowing where the EC firmware resides since some ECs | |
| 51 # boot from bottom of ROM and others from top of ROM. This will be the | |
| 52 # region labeled "fw" | |
| 53 # | |
| 54 # The following example is for a 1MB ROM with 128KB occupied by EC firmware. | |
| 55 # The EC in this example loads firmware from the lowest address. | |
| 56 # 0x000000 0x01ffff fw | |
| 57 # 0x020000 0x0fffff unused | |
| 58 | |
| 59 LOGFILE="${0}.log" | |
| 60 ZERO_4K="00_4k.bin" | |
| 61 FF_4K="ff_4k.bin" | |
| 62 FF_4K_TEXT="ff_4k.txt" | |
| 63 | |
| 64 TESTFILE="test.bin" | |
| 65 | |
| 66 ec_fail() | |
| 67 { | |
| 68 echo "$1" >> ${LOGFILE} | |
| 69 echo "$0: failed" >> ${LOGFILE} | |
| 70 exit ${EXIT_FAILURE} | |
| 71 } | |
| 72 | |
| 73 which uuencode > /dev/null | |
| 74 if [ "$?" != "0" ] ; then | |
| 75 ec_fail "uuencode is required to use this script" | |
| 76 fi | |
| 77 | |
| 78 # FIXME: This is a chromium os -ism. Most distros don't strip out "diff". | |
| 79 which diff > /dev/null | |
| 80 if [ "$?" != "0" ] ; then | |
| 81 ec_fail "diff is required to use this script" | |
| 82 fi | |
| 83 | |
| 84 # FIXME: extra chromium os paranoia | |
| 85 which printf > /dev/null | |
| 86 if [ "$?" != "0" ] ; then | |
| 87 ec_fail "printf is required to use this script" | |
| 88 fi | |
| 89 | |
| 90 echo "User-provided \$ALT_EC_IMAGE: ${ALT_EC_IMAGE}" >> ${LOGFILE} | |
| 91 if [ -z "$ALT_EC_IMAGE" ] || [ ! -e "$ALT_EC_IMAGE" ]; then | |
| 92 ec_fail "Please provide an alternative EC firmware image using the ALT_E C_IMAGE environment variable." | |
| 93 fi | |
| 94 | |
| 95 echo "User-provided \$LAYOUT_FILE: ${LAYOUT_FILE}" >> ${LOGFILE} | |
| 96 if [ -z "$LAYOUT_FILE" ] || [ ! -e "$LAYOUT_FILE" ]; then | |
| 97 ec_fail "Please provide a layout file using the LAYOUT_FILE environment variable" | |
| 98 fi | |
| 99 | |
| 100 ranges=$(awk '{ if ( $2 == "unused" ) print $1 }' "${LAYOUT_FILE}") | |
| 101 range_found=0 | |
| 102 for range in $ranges; do | |
| 103 start=$(echo $range | awk -F":" '{ print $1 }') | |
| 104 end=$(echo $range | awk -F":" '{ print $2 }') | |
| 105 len=$((${end} - ${start})) | |
| 106 | |
| 107 echo "Testing if range is usable: ${start}:${end}, len=${len}" >> ${LOGF ILE} | |
| 108 if [ ${len} -lt $((0x1ffff)) ]; then | |
| 109 continue | |
| 110 else | |
| 111 range_found=1 | |
| 112 break | |
| 113 fi | |
| 114 done | |
| 115 | |
| 116 if [ $range_found -ne 1 ]; then | |
| 117 ec_fail "No suitable unused range found" | |
| 118 else | |
| 119 echo "Found usable range: ${start}:${end}, len=${len}" | |
| 120 fi | |
| 121 | |
| 122 # Make 4k worth of 0xff bytes | |
| 123 echo "begin 640 $FF_4K" > "$FF_4K_TEXT" | |
| 124 i=0 | |
| 125 while [ $i -le 90 ]; do | |
| 126 echo "M____________________________________________________________" >> "$FF_4K_TEXT" | |
| 127 i=$((${i} + 1)) | |
| 128 done | |
| 129 echo "!_P``" >> "$FF_4K_TEXT" | |
| 130 echo "\`" >> "$FF_4K_TEXT" | |
| 131 echo "end" >> "$FF_4K_TEXT" | |
| 132 uudecode -o "$FF_4K" "$FF_4K_TEXT" | |
| 133 rm -f "$FF_4K_TEXT" | |
| 134 | |
| 135 # Make 4k worth of 0x00 bytes | |
| 136 dd if=/dev/zero of="$ZERO_4K" bs=1 count=4096 2> /dev/null | |
| 137 echo "ffh pattern written in ${FF_4K}" | |
| 138 echo "00h pattern written in ${ZERO_4K}" | |
| 139 | |
| 140 # Actual tests are performed below. | |
| 141 # | |
| 142 NUM_REGIONS=16 | |
| 143 | |
| 144 # Make a layout - 4K regions on 4K boundaries. This will test basic | |
| 145 # functionality of erasing and writing specific blocks. | |
| 146 #FIXME: the layout file is in dec rather than hex. Yuck! Do we care enough | |
| 147 # to filter the output thru bc or something and convert to hex? | |
| 148 echo " | |
| 149 `printf 0x%x $((${start} + 0x00000))`:`printf 0x%x $((${start} + 0x00fff))` 00_0 | |
|
Stefan Reinauer
2010/11/23 19:05:30
Would it make sense to pack this into a separate f
hailfinger
2010/11/23 20:05:34
Can you try to keep the diff to the normal partial
Stefan Reinauer
2010/11/23 21:14:14
Yepp. It would be nice to see some kind of generic
dhendrix
2010/11/24 02:48:14
I managed to compress this stuff into a loop -- go
| |
| 150 `printf 0x%x $((${start} + 0x01000))`:`printf 0x%x $((${start} + 0x01fff))` ff_0 | |
| 151 | |
| 152 `printf 0x%x $((${start} + 0x02000))`:`printf 0x%x $((${start} + 0x02fff))` 00_1 | |
| 153 `printf 0x%x $((${start} + 0x03000))`:`printf 0x%x $((${start} + 0x03fff))` ff_1 | |
| 154 | |
| 155 `printf 0x%x $((${start} + 0x04000))`:`printf 0x%x $((${start} + 0x04fff))` 00_2 | |
| 156 `printf 0x%x $((${start} + 0x05000))`:`printf 0x%x $((${start} + 0x05fff))` ff_2 | |
| 157 | |
| 158 `printf 0x%x $((${start} + 0x06000))`:`printf 0x%x $((${start} + 0x06fff))` 00_3 | |
| 159 `printf 0x%x $((${start} + 0x07000))`:`printf 0x%x $((${start} + 0x07fff))` ff_3 | |
| 160 | |
| 161 `printf 0x%x $((${start} + 0x08000))`:`printf 0x%x $((${start} + 0x08fff))` 00_4 | |
| 162 `printf 0x%x $((${start} + 0x09000))`:`printf 0x%x $((${start} + 0x09fff))` ff_4 | |
| 163 | |
| 164 `printf 0x%x $((${start} + 0x0a000))`:`printf 0x%x $((${start} + 0x0afff))` 00_5 | |
| 165 `printf 0x%x $((${start} + 0x0b000))`:`printf 0x%x $((${start} + 0x0bfff))` ff_5 | |
| 166 | |
| 167 `printf 0x%x $((${start} + 0x0c000))`:`printf 0x%x $((${start} + 0x0cfff))` 00_6 | |
| 168 `printf 0x%x $((${start} + 0x0d000))`:`printf 0x%x $((${start} + 0x0dfff))` ff_6 | |
| 169 | |
| 170 `printf 0x%x $((${start} + 0x0e000))`:`printf 0x%x $((${start} + 0x0efff))` 00_7 | |
| 171 `printf 0x%x $((${start} + 0x0f000))`:`printf 0x%x $((${start} + 0x0ffff))` ff_7 | |
| 172 | |
| 173 `printf 0x%x $((${start} + 0x10000))`:`printf 0x%x $((${start} + 0x10fff))` 00_8 | |
| 174 `printf 0x%x $((${start} + 0x11000))`:`printf 0x%x $((${start} + 0x11fff))` ff_8 | |
| 175 | |
| 176 `printf 0x%x $((${start} + 0x12000))`:`printf 0x%x $((${start} + 0x12fff))` 00_9 | |
| 177 `printf 0x%x $((${start} + 0x13000))`:`printf 0x%x $((${start} + 0x13fff))` ff_9 | |
| 178 | |
| 179 `printf 0x%x $((${start} + 0x14000))`:`printf 0x%x $((${start} + 0x14fff))` 00_1 0 | |
| 180 `printf 0x%x $((${start} + 0x15000))`:`printf 0x%x $((${start} + 0x15fff))` ff_1 0 | |
| 181 | |
| 182 `printf 0x%x $((${start} + 0x16000))`:`printf 0x%x $((${start} + 0x16fff))` 00_1 1 | |
| 183 `printf 0x%x $((${start} + 0x17000))`:`printf 0x%x $((${start} + 0x17fff))` ff_1 1 | |
| 184 | |
| 185 `printf 0x%x $((${start} + 0x18000))`:`printf 0x%x $((${start} + 0x18fff))` 00_1 2 | |
| 186 `printf 0x%x $((${start} + 0x19000))`:`printf 0x%x $((${start} + 0x19fff))` ff_1 2 | |
| 187 | |
| 188 `printf 0x%x $((${start} + 0x1a000))`:`printf 0x%x $((${start} + 0x1afff))` 00_1 3 | |
| 189 `printf 0x%x $((${start} + 0x1b000))`:`printf 0x%x $((${start} + 0x1bfff))` ff_1 3 | |
| 190 | |
| 191 `printf 0x%x $((${start} + 0x1c000))`:`printf 0x%x $((${start} + 0x1cfff))` 00_1 4 | |
| 192 `printf 0x%x $((${start} + 0x1d000))`:`printf 0x%x $((${start} + 0x1dfff))` ff_1 4 | |
| 193 | |
| 194 `printf 0x%x $((${start} + 0x1e000))`:`printf 0x%x $((${start} + 0x1efff))` 00_1 5 | |
| 195 `printf 0x%x $((${start} + 0x1f000))`:`printf 0x%x $((${start} + 0x1ffff))` ff_1 5 | |
| 196 " > layout_ec_4k_aligned.txt | |
| 197 | |
| 198 cp "${BACKUP}" "$TESTFILE" | |
| 199 i=0 | |
| 200 while [ $i -lt $NUM_REGIONS ] ; do | |
| 201 tmpstr="aligned region ${i} test: " | |
| 202 offset=$((${start} + $((${i} * 8192)))) | |
| 203 dd if=${ZERO_4K} of=${TESTFILE} bs=1 conv=notrunc seek=${offset} 2> /dev /null | |
| 204 dd if=${FF_4K} of=${TESTFILE} bs=1 conv=notrunc seek=$((${offset} + 4096 )) 2> /dev/null | |
| 205 | |
| 206 ./flashrom ${FLASHROM_PARAM} -l layout_ec_4k_aligned.txt -i 00_${i} -i f f_${i} -w "$TESTFILE" 2> /dev/null | |
| 207 if [ "$?" != "0" ] ; then | |
| 208 ec_fail "failed to flash region" | |
| 209 fi | |
| 210 | |
| 211 # download the entire ROM image and use diff to compare to ensure | |
| 212 # flashrom logic does not violate user-specified regions | |
| 213 flashrom ${FLASHROM_PARAM} -r difftest.bin 2> /dev/null | |
| 214 diff -q difftest.bin "$TESTFILE" | |
| 215 if [ "$?" != "0" ] ; then | |
| 216 ec_fail "failed diff test" | |
| 217 fi | |
| 218 rm -f difftest.bin | |
| 219 | |
| 220 i=$((${i} + 1)) | |
| 221 echo "${tmpstr}passed" >> ${LOGFILE} | |
| 222 done | |
| 223 | |
| 224 # Make a layout - 4K regions on 4.5K boundaries. This will help find problems | |
| 225 # with logic that only operates on part of a block. For example, if a user | |
| 226 # wishes to re-write a fraction of a block, then: | |
| 227 # 1. The whole block must be erased. | |
| 228 # 2. The old content must be restored at unspecified offsets. | |
| 229 # 3. The new content must be written at specified offsets. | |
| 230 # | |
| 231 # Note: The last chunk of 0xff bytes is only 2K as to avoid overrunning a 128KB | |
| 232 # test region. | |
| 233 # | |
| 234 echo " | |
| 235 `printf 0x%x $((${start} + 0x00800))`:`printf 0x%x $((${start} + 0x017ff))` 00_0 | |
| 236 `printf 0x%x $((${start} + 0x01800))`:`printf 0x%x $((${start} + 0x027ff))` ff_0 | |
| 237 | |
| 238 `printf 0x%x $((${start} + 0x02800))`:`printf 0x%x $((${start} + 0x037ff))` 00_1 | |
| 239 `printf 0x%x $((${start} + 0x03800))`:`printf 0x%x $((${start} + 0x047ff))` ff_1 | |
| 240 | |
| 241 `printf 0x%x $((${start} + 0x04800))`:`printf 0x%x $((${start} + 0x057ff))` 00_2 | |
| 242 `printf 0x%x $((${start} + 0x05800))`:`printf 0x%x $((${start} + 0x067ff))` ff_2 | |
| 243 | |
| 244 `printf 0x%x $((${start} + 0x06800))`:`printf 0x%x $((${start} + 0x077ff))` 00_3 | |
| 245 `printf 0x%x $((${start} + 0x07800))`:`printf 0x%x $((${start} + 0x087ff))` ff_3 | |
| 246 | |
| 247 `printf 0x%x $((${start} + 0x08800))`:`printf 0x%x $((${start} + 0x097ff))` 00_4 | |
| 248 `printf 0x%x $((${start} + 0x09800))`:`printf 0x%x $((${start} + 0x0a7ff))` ff_4 | |
| 249 | |
| 250 `printf 0x%x $((${start} + 0x0a800))`:`printf 0x%x $((${start} + 0x0b7ff))` 00_5 | |
| 251 `printf 0x%x $((${start} + 0x0b800))`:`printf 0x%x $((${start} + 0x0c7ff))` ff_5 | |
| 252 | |
| 253 `printf 0x%x $((${start} + 0x0c800))`:`printf 0x%x $((${start} + 0x0d7ff))` 00_6 | |
| 254 `printf 0x%x $((${start} + 0x0d800))`:`printf 0x%x $((${start} + 0x0e7ff))` ff_6 | |
| 255 | |
| 256 `printf 0x%x $((${start} + 0x0e800))`:`printf 0x%x $((${start} + 0x0f7ff))` 00_7 | |
| 257 `printf 0x%x $((${start} + 0x0f800))`:`printf 0x%x $((${start} + 0x107ff))` ff_7 | |
| 258 | |
| 259 `printf 0x%x $((${start} + 0x10800))`:`printf 0x%x $((${start} + 0x117ff))` 00_8 | |
| 260 `printf 0x%x $((${start} + 0x11800))`:`printf 0x%x $((${start} + 0x127ff))` ff_8 | |
| 261 | |
| 262 `printf 0x%x $((${start} + 0x12800))`:`printf 0x%x $((${start} + 0x137ff))` 00_9 | |
| 263 `printf 0x%x $((${start} + 0x13800))`:`printf 0x%x $((${start} + 0x147ff))` ff_9 | |
| 264 | |
| 265 `printf 0x%x $((${start} + 0x14800))`:`printf 0x%x $((${start} + 0x157ff))` 00_1 0 | |
| 266 `printf 0x%x $((${start} + 0x15800))`:`printf 0x%x $((${start} + 0x167ff))` ff_1 0 | |
| 267 | |
| 268 `printf 0x%x $((${start} + 0x16800))`:`printf 0x%x $((${start} + 0x177ff))` 00_1 1 | |
| 269 `printf 0x%x $((${start} + 0x17800))`:`printf 0x%x $((${start} + 0x187ff))` ff_1 1 | |
| 270 | |
| 271 `printf 0x%x $((${start} + 0x18800))`:`printf 0x%x $((${start} + 0x197ff))` 00_1 2 | |
| 272 `printf 0x%x $((${start} + 0x19800))`:`printf 0x%x $((${start} + 0x1a7ff))` ff_1 2 | |
| 273 | |
| 274 `printf 0x%x $((${start} + 0x1a800))`:`printf 0x%x $((${start} + 0x1b7ff))` 00_1 3 | |
| 275 `printf 0x%x $((${start} + 0x1b800))`:`printf 0x%x $((${start} + 0x1c7ff))` ff_1 3 | |
| 276 | |
| 277 `printf 0x%x $((${start} + 0x1c800))`:`printf 0x%x $((${start} + 0x1d7ff))` 00_1 4 | |
| 278 `printf 0x%x $((${start} + 0x1d800))`:`printf 0x%x $((${start} + 0x1e7ff))` ff_1 4 | |
| 279 | |
| 280 `printf 0x%x $((${start} + 0x1e800))`:`printf 0x%x $((${start} + 0x1f7ff))` 00_1 5 | |
| 281 `printf 0x%x $((${start} + 0x1f800))`:`printf 0x%x $((${start} + 0x1ffff))` ff_1 5 | |
| 282 " > layout_ec_unaligned.txt | |
| 283 | |
| 284 # reset the test file and ROM to the original state | |
| 285 flashrom ${FLASHROM_PARAM} -w "${BACKUP}" > /dev/null | |
| 286 cp "$BACKUP" "$TESTFILE" | |
| 287 | |
| 288 i=0 | |
| 289 while [ $i -lt $NUM_REGIONS ] ; do | |
| 290 echo -n "unaligned region ${i} test: " | |
| 291 | |
| 292 offset=$(($((${i} * 8192)) + 2048)) | |
| 293 # Protect against too long write | |
| 294 writelen=4096 | |
| 295 if [ $((${offset} + 4096 + 4096)) -ge 131072 ]; then | |
| 296 writelen=$((131072 - $((${offset} + 4096)))) | |
| 297 if [ ${writelen} -lt 0 ]; then | |
| 298 writelen=0 | |
| 299 fi | |
| 300 fi | |
| 301 dd if=${ZERO_4K} of=${TESTFILE} bs=1 conv=notrunc seek=${offset} 2> /dev /null | |
| 302 dd if=${FF_4K} of=${TESTFILE} bs=1 conv=notrunc seek=$((${offset} + 4096 )) count=writelen 2> /dev/null | |
| 303 | |
| 304 ./flashrom ${FLASHROM_PARAM} -l layout_ec_unaligned.txt -i 00_${i} -i ff _${i} -w "$TESTFILE" 2> /dev/null | |
| 305 if [ "$?" != "0" ] ; then | |
| 306 partial_writes_fail "failed to flash region" | |
| 307 fi | |
| 308 | |
| 309 # download the entire ROM image and use diff to compare to ensure | |
| 310 # flashrom logic does not violate user-specified regions | |
| 311 flashrom ${FLASHROM_PARAM} -r difftest.bin 2> /dev/null | |
| 312 diff -q difftest.bin "$TESTFILE" | |
| 313 if [ "$?" != "0" ] ; then | |
| 314 partial_writes_fail "failed diff test" | |
| 315 fi | |
| 316 rm -f difftest.bin | |
| 317 | |
| 318 i=$((${i} + 1)) | |
| 319 echo "passed" | |
| 320 done | |
| 321 | |
| 322 return "$EXIT_SUCCESS" | |
| OLD | NEW |