partial_writes_ec.sh 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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 to a temporary location, the
  30. # environment variables must 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. . "$(pwd)/common.sh"
  59. logfile="${0}.log"
  60. zero_4k="00_4k.bin"
  61. ff_4k="ff_4k.bin"
  62. ff_4k_text="ff_4k.txt"
  63. num_regions=16
  64. testfile="test.bin"
  65. partial_writes_ec_fail()
  66. {
  67. echo "$1" >> ${logfile}
  68. echo "$0: failed" >> ${logfile}
  69. exit ${EXIT_FAILURE}
  70. }
  71. which uuencode > /dev/null || partial_writes_ec_fail "uuencode is required to use this script"
  72. which diff > /dev/null || partial_writes_ec_fail "diff is required to use this script"
  73. which printf > /dev/null || partial_writes_ec_fail "printf is required to use this script"
  74. echo "User-provided \$ALT_EC_IMAGE: ${ALT_EC_IMAGE}" >> ${logfile}
  75. if [ -z "$ALT_EC_IMAGE" ] || [ ! -e "$ALT_EC_IMAGE" ]; then
  76. partial_writes_ec_fail "Please provide absolute path to alternate EC firmware image using the ALT_EC_IMAGE environment variable."
  77. fi
  78. echo "User-provided \$LAYOUT_FILE: ${LAYOUT_FILE}" >> ${logfile}
  79. if [ -z "$LAYOUT_FILE" ] || [ ! -e "$LAYOUT_FILE" ]; then
  80. partial_writes_ec_fail "Please provide absolute path to layout file using the LAYOUT_FILE environment variable"
  81. fi
  82. #
  83. # Part 1: Write an alternate firmware image to the "fw" region in EC flash
  84. #
  85. do_test_flashrom -l ${LAYOUT_FILE} -i fw -w "${ALT_EC_IMAGE}"
  86. if [ $? -ne 0 ]; then
  87. partial_writes_ec_fail "Failed to write alternate EC firmware" >> ${logfile}
  88. else
  89. echo "Wrote alternate EC firmware image successfully" >> ${logfile}
  90. fi
  91. # Restore original firmware region
  92. do_test_flashrom -l ${LAYOUT_FILE} -i fw -w "${BACKUP}"
  93. if [ $? -ne 0 ]; then
  94. partial_writes_ec_fail "Failed to restore original EC firmware" >> ${logfile}
  95. else
  96. echo "Restored original firmware image successfully" >> ${logfile}
  97. fi
  98. #
  99. # Part 2: Write a pattern to an "unused" region in EC flash
  100. #
  101. ranges=$(awk '{ if ( $2 == "unused" ) print $1 }' "${LAYOUT_FILE}")
  102. range_found=0
  103. for range in $ranges; do
  104. start=$(echo $range | awk -F":" '{ print $1 }')
  105. end=$(echo $range | awk -F":" '{ print $2 }')
  106. len=$((${end} - ${start}))
  107. echo "Testing if range is usable: ${start}:${end}, len=${len}" >> ${logfile}
  108. if [ ${len} -lt $(($((${num_regions} - 1)) * 4096)) ]; then
  109. continue
  110. else
  111. range_found=1
  112. break
  113. fi
  114. done
  115. if [ $range_found -ne 1 ]; then
  116. partial_writes_ec_fail "No suitable unused range found"
  117. else
  118. echo "Found usable range: ${start}:${end}, len=${len}"
  119. fi
  120. # Make 4k worth of 0xff bytes
  121. echo "begin 640 $ff_4k" > "$ff_4k_text"
  122. i=0
  123. while [ $i -le 90 ]; do
  124. echo "M____________________________________________________________" >> "$ff_4k_text"
  125. i=$((${i} + 1))
  126. done
  127. echo "!_P``" >> "$ff_4k_text"
  128. echo "\`" >> "$ff_4k_text"
  129. echo "end" >> "$ff_4k_text"
  130. uudecode -o "$ff_4k" "$ff_4k_text"
  131. rm -f "$ff_4k_text"
  132. # Make 4k worth of 0x00 bytes
  133. dd if=/dev/zero of="$zero_4k" bs=1 count=4096 2> /dev/null
  134. echo "ffh pattern written in ${ff_4k}"
  135. echo "00h pattern written in ${zero_4k}"
  136. # Actual tests are performed below.
  137. #
  138. # Make a layout - 4K regions on 4K boundaries. This will test basic
  139. # functionality of erasing and writing specific blocks.
  140. for i in `seq 0 $((${num_regions} - 1))` ; do
  141. offset_00=$((${i} * 8192))
  142. offset_ff=$((${i} * 8192 + 4096))
  143. echo "\
  144. `printf 0x%x $((${start} + ${offset_00}))`:`printf 0x%x $((${start} + ${offset_00} + 0xfff))` 00_${i}
  145. `printf 0x%x $((${start} + ${offset_ff}))`:`printf 0x%x $((${start} + ${offset_ff} + 0xfff))` ff_${i}
  146. " >> layout_ec_4k_aligned.txt
  147. done
  148. cp "${BACKUP}" "$testfile"
  149. i=0
  150. while [ $i -lt $num_regions ] ; do
  151. tmpstr="aligned region ${i} test: "
  152. offset=$((${start} + $((${i} * 8192))))
  153. dd if=${zero_4k} of=${testfile} bs=1 conv=notrunc seek=${offset} 2> /dev/null
  154. dd if=${ff_4k} of=${testfile} bs=1 conv=notrunc seek=$((${offset} + 4096)) 2> /dev/null
  155. do_test_flashrom -l layout_ec_4k_aligned.txt -i 00_${i} -i ff_${i} -w "$testfile"
  156. if [ $? -ne 0 ] ; then
  157. partial_writes_ec_fail "${tmpstr}failed to flash"
  158. fi
  159. # download the entire ROM image and use diff to compare to ensure
  160. # flashrom logic does not violate user-specified regions
  161. flashrom ${FLASHROM_PARAM} -r difftest.bin 2> /dev/null
  162. diff -q difftest.bin "$testfile"
  163. if [ $? -ne 0 ] ; then
  164. partial_writes_ec_fail "${tmpstr}failed diff test"
  165. fi
  166. rm -f difftest.bin
  167. i=$((${i} + 1))
  168. echo "${tmpstr}passed" >> ${logfile}
  169. done
  170. # Make a layout - 4K regions on 4.5K boundaries. This will help find problems
  171. # with logic that only operates on part of a block. For example, if a user
  172. # wishes to re-write a fraction of a block, then:
  173. # 1. The whole block must be erased.
  174. # 2. The old content must be restored at unspecified offsets.
  175. # 3. The new content must be written at specified offsets.
  176. #
  177. # Note: The last chunk of 0xff bytes is too long, so special logic was added to
  178. # below to avoid overrunning a 128KB test region.
  179. #
  180. for i in `seq 0 $((${num_regions} - 1))` ; do
  181. offset_00=$((${i} * 8192 + 2048))
  182. offset_ff=$((${i} * 8192 + 4096 + 2048))
  183. echo "\
  184. `printf 0x%06x $((${start} + ${offset_00}))`:`printf 0x%06x $((${start} + ${offset_00} + 0xfff))` 00_${i}
  185. `printf 0x%06x $((${start} + ${offset_ff}))`:`printf 0x%06x $((${start} + ${offset_ff} + 0xfff))` ff_${i}
  186. " >> layout_ec_unaligned.txt
  187. done
  188. # reset the test file and ROM to the original state
  189. flashrom ${FLASHROM_PARAM} -w "${BACKUP}" > /dev/null
  190. cp "$BACKUP" "$testfile"
  191. i=0
  192. while [ $i -lt $num_regions ] ; do
  193. tmpstr="unaligned region ${i} test: "
  194. offset=$(($((${i} * 8192)) + 2048))
  195. # Protect against too long write
  196. writelen=4096
  197. if [ $((${offset} + 4096 + 4096)) -ge 131072 ]; then
  198. writelen=$((131072 - $((${offset} + 4096))))
  199. if [ ${writelen} -lt 0 ]; then
  200. writelen=0
  201. fi
  202. fi
  203. dd if=${zero_4k} of=${testfile} bs=1 conv=notrunc seek=$((${start} + ${offset})) 2> /dev/null
  204. dd if=${ff_4k} of=${testfile} bs=1 conv=notrunc seek=$((${start} + ${offset} + 4096)) count=writelen 2> /dev/null
  205. do_test_flashrom -l layout_ec_unaligned.txt -i 00_${i} -i ff_${i} -w "$testfile"
  206. if [ $? -ne 0 ] ; then
  207. partial_writes_ec_fail "${tmpstr}failed to flash region"
  208. fi
  209. # download the entire ROM image and use diff to compare to ensure
  210. # flashrom logic does not violate user-specified regions
  211. flashrom ${FLASHROM_PARAM} -r difftest.bin 2> /dev/null
  212. diff -q difftest.bin "$testfile"
  213. if [ $? -ne 0 ] ; then
  214. partial_writes_ec_fail "${tmpstr}failed diff test"
  215. fi
  216. rm -f difftest.bin
  217. i=$((${i} + 1))
  218. echo "${tmpstr}passed" >> ${logfile}
  219. done
  220. return "$EXIT_SUCCESS"