Commit Graph

498 Commits

Author SHA1 Message Date
Tao Bao
d42e97ebb4 Build recovery-two-step.img for two-step OTAs.
In two-step OTAs, we write recovery image to /boot as the first step so
that we can reboot from there and install a new recovery image to
/recovery. However, bootloader will show "Your device is corrupt"
message when booting /boot with the recovery image. Because the recovery
image encodes the path of "/recovery" as part of the signature metadata,
which fails the verified boot.

This CL generates a special "recovery-two-step.img" in addition to the
regular recovery.img. This image encodes "/boot" when being signed,
which will be flashed to /boot at stage 1/3 in a two-step OTA.

Here are the desired changes:

- 'IMAGES/recovery-two-step.img' exists in target_files.zip for non-A/B
targets (e.g. bullhead). The image should not exist for targets that
don't have a recovery partition (e.g. A/B devices like sailfish).

- <device>-img.zip should not contain 'recovery-two-step.img'.

- Nothing should change when building non-two-step OTAs. For two-step
OTAs, 'recovery-two-step.img' should be included in the OTA package;
'updater-script' should flash this image to /boot at stage 1/3.

- When building a two-step OTA with an input TF.zip that doesn't have
  IMAGES/recovery-two-step.img, it should use the existing
  IMAGES/recovery.img instead.

Bug: 32986477
Test: Tested the steps above on bullhead and sailfish.
Change-Id: I34e6c599bcf2011d4cd5c926999418b3975d6d0f
2016-12-01 17:47:59 -08:00
Tao Bao
2e3f1c5258 Merge "releasetools: Remove dead parameter in GetBootableImage()."
am: 8df4fea85f

Change-Id: I192af3927849d0d8f995f0002b8b8f2e191b794f
2016-12-01 17:09:07 +00:00
Tao Bao
2a4336bc04 releasetools: Remove dead parameter in GetBootableImage().
The 'system_img_path' parameter was introduced in commit
d995f4b04d, but became obsolete since
commit 2ce63edab7.

Test: m dist
Change-Id: Iffd496d929db5cc3dfc955a48bfc1b1317bd012f
2016-12-01 00:08:27 -08:00
Tao Bao
dc04f93e39 Merge "releasetools: Use java_path in sign_target_files_apks.py."
am: 4a71d500c1

Change-Id: I61400574ac3f7d29906ca571f497554631ecd72d
2016-11-08 23:42:26 +00:00
Tao Bao
e95540e060 releasetools: Use java_path in sign_target_files_apks.py.
Prior to this CL, it was calling the hard-coded "java" although it was
accepting a "--java_path" option.

Also switch OPTIONS.java_args from string to list. Otherwise it won't
work when providing multiple args.

Bug: 32737832
Test: Specify "--java_path=" and "--java_args" when invoking
      sign_target_files_apks.py with "-v". Check the commands being
      called.
Change-Id: Id7ef98e778646d532027434de7fba9b7a104dbd0
2016-11-08 12:48:43 -08:00
Tao Bao
9242e1f750 Merge "releasetools: compare size between compressed and patch while build otapackage"
am: 49758959f2

Change-Id: I17b988878cc7ffdfbe490f404c9cd5ab996a8c5f
2016-11-05 00:13:55 +00:00
YOUNG HO CHA
ccc5c40523 releasetools: compare size between compressed and patch while build otapackage
Currently, whether contains patch or verbatim, compute with file size
and patch size.
But ota file must be compressed with zip, so it should be better with
compressed size than uncompressed.

Test: aosp_shamu-user build without proprietary blobs between MOB30P and NRD90S
$ du -k ota_shamu_old.zip ota_shamu_new.zip
217252	ota_shamu_old.zip
216520	ota_shamu_new.zip

Change-Id: If68cb1fbe2f7815067451915a0dcfe93ea5ba8d6
Signed-off-by: YOUNG HO CHA <ganadist@gmail.com>
2016-10-18 17:27:09 +09:00
Tao Bao
8145c70f2b Merge "releasetools: Fix the reference to OPTIONS.info_dict." am: 0a5b59e78b am: 8b6d59e110
am: b00dbd1b11

Change-Id: Ib31adf3e30f4b9077e14c577ffdc5791e89b746b
2016-09-30 17:59:31 +00:00
Tao Bao
b31b94e159 releasetools: Fix the reference to OPTIONS.info_dict.
sign_target_files_apks.py calls common.GetBootableImage() but without
calling 'OPTIONS = common.OPTIONS' first. In common.GetBootableImage(),
we should use the local info_dict parameter instead of OPTIONS.info_dict.

Test: sign_target_files_apks.py generates signed-TF.zip successfully.

Change-Id: Ia3d32b88691c26e5fb98feea709e3e3c3eb70fdb
2016-09-29 22:04:50 -07:00
David Zeuthen
27ac0e34fe resolve merge conflicts of c36ab42 to nyc-mr1-dev-plus-aosp
Change-Id: Iaf78fb6c723955fd92cc64194cb32bba73a9dafb
2016-09-29 14:25:03 -04:00
David Zeuthen
2ce63edab7 Update for new Android Verified Boot (AVB).
This updates the build system for the new Android Verified Boot
codebase. As this is based on Brillo Verified Boot, this change replaces
the existing BVB support.

Android Verified Boot is enabled by the BOARD_AVB_ENABLE variable

 BOARD_AVB_ENABLE := true

This will make the build system create vbmeta.img which will contain a
hash descriptor for boot.img, a hashtree descriptor for system.img, a
kernel-cmdline descriptor for setting up dm-verity for system.img and
append a hash-tree to system.img.

Additionally, the descriptors are left in boot.img and system.img so a
third party can create their own vbmeta.img file linking - using the
option --chain_partition - to these images. If this is not needed
footers can be erased using the 'avbtool erase_footer' command. It's
also harmless to just leave them in the images.

By default, the algorithm SHA256_RSA4096 is used with a test key from
the AVB source directory. This can be overriden by the
BOARD_AVB_ALGORITHM and BOARD_AVB_KEY_PATH variables to use e.g. a
4096-bit RSA key and SHA-512:

 BOARD_AVB_ALGORITHM := SHA512_RSA4096
 BOARD_AVB_KEY_PATH := /path/to/rsa_key_4096bits.pem

To prevent rollback attacks, the rollback index should be increased on a
regular basis. The rollback index can be set with the
BOARD_AVB_ROLLBACK_INDEX variable:

 BOARD_AVB_ROLLBACK_INDEX := 5

If this is not set, the rollback index defaults to 0.

The variable BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS can be used to specify
additional options passed to 'avbtool make_vbmeta_image'. Typical
options to be used here include '--prop', '--prop_from_file', and
'--chain_partition'.

The variable BOARD_AVBTOOL_BOOT_ADD_HASH_FOOTER_ARGS can be used to
specify additional options passed to 'avbtool add_hash_footer' for
boot.img. Typical options to be used here include '--hash_algorithm' and
'--salt'.

The variable BOARD_AVBTOOL_SYSTEM_ADD_HASHTREE_FOOTER_ARGS can be used
to specify additional options passed to 'avbtool add_hashtree_footer'
for systems.img. Typical options to be used here include
'--hash_algorithm', '--salt', and '--block_size'.

BUG=31264226
TEST=Manually tested on edison-eng by inspecting {boot, system,
  vbmeta}.img in out/ directory as well as their counterparts in
  the IMAGES/ directory of edision-target_files-eng.zeuthen.zip

Merged-In: Ic9a61cfc65c148b12996e57f04da5432eef6b982

Change-Id: I97042655bca15e7eac899f12c5bada2f6184d307
2016-09-29 11:19:36 -04:00
Tao Bao
4c851b1098 Change the default parameter values in common.MakeTempFile().
tempfile.TemporaryFile() complains when 'None' is passed as the
prefix/suffix. It uses prefix='tmp' and suffix='' as the default values
and we should do the same.

Test: Call check_ota_package_signature.py and ota_from_target_files.py
and they still work.

Change-Id: I7fb023a3fd0b1a57c009631d0c57a7bb8e4cb5a3
2016-09-19 13:58:49 -07:00
Tianjie Xu
737afb98c9 resolve merge conflicts of 333df6c to nyc-mr1-dev-plus-aosp
Change-Id: Ibe66a7c78073a9c3e9f139bd6b00a0afab075190
2016-07-11 11:42:53 -07:00
Tianjie Xu
cfa86223d6 Add care_map to target_files package
Generate a new file containing care_data of system (and vendor)
partition, and add it under META/ of target file package. For
A/B update, copy this file to OTA package for later use by
update_verifier.

Bug: 27175949

Change-Id: I90bb972703afaeb94bc3efe718fd81b1cfbcabcc
2016-07-08 16:53:59 -07:00
Ethan Xia
e4efe69fae Merge \\"releasetools: Change the default key path for bvbtool\\" am: 7c7571d510
am: 090e8eff5e

Change-Id: I34f3cc1a38b860fd3100548f55a38af9faf69e19
2016-06-28 01:59:47 +00:00
Ethan Xia
090e8eff5e Merge \"releasetools: Change the default key path for bvbtool\"
am: 7c7571d510

Change-Id: Ic02f432c689edba37ecce684662d8f5f1cfc32b6
2016-06-28 01:57:26 +00:00
Ethan Xia
37b4a9819b releasetools: Change the default key path for bvbtool
The bvb path has been changed from 'system/bvb' to 'external/bvb'

Change-Id: I8587351b7d702a287883c6bd3c9de1cd3540435b
2016-06-27 17:19:01 +08:00
Elliott Hughes
f66d3e61f8 Merge \\"Remove obsolete MTD support from the releasetools scripts.\\" am: 63fc2b6766
am: ece6ff869c

Change-Id: I4b5f5b6a622a2fbb996861e8832e1fc1d12e6bf4
2016-06-17 05:02:05 +00:00
Elliott Hughes
ece6ff869c Merge \"Remove obsolete MTD support from the releasetools scripts.\"
am: 63fc2b6766

Change-Id: I26ed21479ab52d535bcc99b13e55a1476a02f76c
2016-06-17 04:59:26 +00:00
Elliott Hughes
305b088729 Remove obsolete MTD support from the releasetools scripts.
Bug: http://b/29250988
Change-Id: I653dc306485c6b35411840b53211d42eb6d19e34
2016-06-16 20:48:47 -07:00
Tao Bao
46ff838582 Merge \"releasetools: Disable using imgdiff for squashfs.\" into nyc-dev
am: a8d3741f1a

Change-Id: If8392b72a865f53449a1d5ca7b52de7697c4b412
2016-06-15 16:12:52 +00:00
Tao Bao
293fd135c7 releasetools: Disable using imgdiff for squashfs.
We use imgdiff to handle files in zip format (e.g. jar/zip/apk) for
higher compression ratio.

For system/vendor in squashfs, a) all files are compressed in LZ4
format; b) we use 4096-byte block size in their sparse images, but the
files in squashfs may not be laid out as 4K-aligned. So the blocks for
a given file as listed in block map may not form a valid zip file, which
may fail the patch generation with imgdiff.

Disable using imgdiff for squashfs images, and use bsdiff instead.

Bug: 22322817
Change-Id: Ie76aa4cece5c9d38cb1d1a34c505a4a8f37512d3
2016-06-13 10:04:23 -07:00
Tianjie Xu
97be5b9b6e Merge "Report error codes in the OTA update script" into nyc-dev
am: 654e4fb023

* commit '654e4fb02368b05cbfba3246b4c634512fa84464':
  Report error codes in the OTA update script

Change-Id: I333bd45886d5915858b762e086d8a263f81b26e2
2016-05-25 21:11:12 +00:00
Tianjie Xu
209db46be1 Report error codes in the OTA update script
Modify the abort() function in the OTA update generation script to
report an error code. The recoveryimage will parse the code and write it
into last_install for further data analysis.

Bug: 28934032
Change-Id: I2d62f81fd352c3102fb84f054972ac0ecb965a21
2016-05-25 12:22:31 -07:00
Tao Bao
e094740249 releasetools: Change the base_fs assertion into warnings.
am: b079b50e2a

* commit 'b079b50e2ae2748f77139618cd5dfb8ef06d8418':
  releasetools: Change the base_fs assertion into warnings.

Change-Id: Iaa24f81e864886ef6f4ebe05ea514fa977306fb4
2016-05-03 16:59:17 +00:00
Tao Bao
b079b50e2a releasetools: Change the base_fs assertion into warnings.
commit f54216f292 packed the base_fs files
into target_files.zip and added assertion to ensure the existence of the
files. We don't want to fail the OTA generation for the target_files.zip
without the base_fs files. Change the assertion into warnings instead.

Bug: 28547368
Change-Id: I6fd758a0a4fdfff02d1640fa46cf43d971627e26
2016-05-03 08:05:09 -07:00
Tao Bao
be9457cad2 Pack base_fs files into target_files.zip.
am: f54216f292

* commit 'f54216f29238a67aad1199a0e85d09e443740bf0':
  Pack base_fs files into target_files.zip.

Change-Id: Ia68c3a707def1865151f071ca33a3bdc513f9045
2016-05-02 16:45:31 +00:00
Tao Bao
f54216f292 Pack base_fs files into target_files.zip.
Pack the base_fs files ({system,vendor}.map) into target_files.zip,
which would be needed when rebuilding the images at signing.

Reset the base_fs paths to point to the files in META/.

Also add blk_alloc_to_base_fs into otatools.zip.

Bug: 27698960
Change-Id: If4eb274b3f3d839c4365624f46f0dc89bd2fa440
2016-04-30 23:56:10 -07:00
Tao Bao
314719a0b6 Merge "Skip verifying the partition with no changed blocks." into nyc-dev
am: 05ce0a9

* commit '05ce0a94a5a6eec3113b62a39f97401e6a3fb3a0':
  Skip verifying the partition with no changed blocks.

Change-Id: I8a3a9f8fe7bcf25fd719940d883a22a7adcfdef9
2016-04-15 03:29:42 +00:00
Tao Bao
962dfdcdac Skip verifying the partition with no changed blocks.
For incremental BBOTAs, commit [1] changed to verify only the touched
blocks to reduce the update time. This CL fixes the bug when there's no
changed block between the two builds.

[1]: commit d522bdc9ed

Bug: 27813356
Bug: 28195498
Change-Id: Ia752d3cf034c544517458ed15df509d4596e21fa
(cherry picked from commit f9efe284a4)
2016-04-14 20:23:17 -07:00
Tao Bao
f9efe284a4 Skip verifying the partition with no changed blocks.
For incremental BBOTAs, commit [1] changed to verify only the touched
blocks to reduce the update time. This CL fixes the bug when there's no
changed block between the two builds.

[1]: commit d522bdc9ed

Bug: 27813356
Bug: 28195498
Change-Id: Ia752d3cf034c544517458ed15df509d4596e21fa
2016-04-14 16:12:06 -07:00
Tao Bao
24105eaab8 Merge "releasetools: Only verify the blocks to be touched." into nyc-dev
am: 21528c5

* commit '21528c5e053e28cd52d603eded53ffaf36d22637':
  releasetools: Only verify the blocks to be touched.

Change-Id: I053c7da789c44916456109c5153f6628fe38c849
2016-04-14 00:02:41 +00:00
Tao Bao
d4caaae160 releasetools: Only verify the blocks to be touched.
For incremental BBOTAs, we used to verify the integrity of all the
blocks in the source partition. In order to reduce the time cost under
recovery, this CL changes to only verify the blocks that will be touched
in the given OTA package (BBOTA >= 3 only). This is a trade-off between
performance and reliability.

Bug: 27813356
Change-Id: I3975ae6f461f0f7e58d24f1df7df46a449d2988b
(cherry picked from commit d522bdc9ed)
2016-04-13 17:00:34 -07:00
Tao Bao
d522bdc9ed releasetools: Only verify the blocks to be touched.
For incremental BBOTAs, we used to verify the integrity of all the
blocks in the source partition. In order to reduce the time cost under
recovery, this CL changes to only verify the blocks that will be touched
in the given OTA package (BBOTA >= 3 only). This is a trade-off between
performance and reliability.

Bug: 27813356
Change-Id: I3975ae6f461f0f7e58d24f1df7df46a449d2988b
2016-04-12 16:41:01 -07:00
Tianjie Xu
bf7981c24f Merge "Remove post-install verification" into nyc-dev
am: 3ebddd4

* commit '3ebddd40e0b3c0848bb066e1e39c406c7a852100':
  Remove post-install verification

Change-Id: I9622385ef80c32a2a98dbac492fcc45f48f1918d
2016-04-12 22:49:49 +00:00
Tianjie Xu
618a81e818 Remove post-install verification
post-install verification calls range_sha1() and checks if the given
partition has expected contents. It takes roughly 20 seconds on
angler with 2.8G system image. Remove it to speed up OTA update. Also
abort the update if block_image_update() fails, as we were relying on
post-install verification to capture block_image_update() failures.

cherry-picked from commit b2deb22033
Bug: 27729678
Change-Id: I8123cd8929295ec26df247acf6bb51df813771d9
2016-04-12 15:41:14 -07:00
Tianjie Xu
b2deb22033 Remove post-install verification
post-install verification calls range_sha1() and checks if the given
partition has expected contents. It takes roughly 20 seconds on
angler with 2.8G system image. Remove it to speed up OTA update. Also
abort the update if block_image_update() fails, as we were relying on
post-install verification to capture block_image_update() failures.

Bug: 27729678
Change-Id: I8123cd8929295ec26df247acf6bb51df813771d9
2016-04-12 11:40:03 -07:00
David Zeuthen
d995f4b04d Add support for Brillo Verified Boot.
The following variables are introduced

 BOARD_BVB_ENABLE: can be set to true to build boot.img and system.img
 files compatible with Brillo Verfied Boot.

 BOARD_BVB_ROLLBACK_INDEX: can be set to an integer to use for the
 rollback index.

 BOARD_BVB_KEY_PATH, BOARD_BVB_ALGORITHM: If set, the former must be a
 path to the private key used to sign the boot image and the latter must
 be the algorithm to use. If unset, a test-key stored in the tree will
 be used.

 BOARD_BVB_MAKE_BOOT_IMAGE_ARGS: Extra options to pass to 'bvbtool
 make_boot_image'.

 BOARD_BVB_SIGN_BOOT_IMAGE_ARGS: Extra options to pass to 'bvbtool
 sign_boot_image'.

 BOARD_BVB_ADD_IMAGE_HASHES_ARGS: Extra options to pass to 'bvbtool
 add_image_hashes'.

 BOARD_CUSTOM_BVBTOOL: Can be set to specify what bvbtool program to
 use.

The existing BOARD_KERNEL_CMDLINE variable is also used, as are existing
kernel and initrd-related variables. Therefore, simply adding

 BOARD_BVB_ENABLE := true

to an existing Makefile should do the trick.

Bug: 26185038
TEST=Added 'BOARD_BVB_ENABLE := true' to hardware/bsp/intel/soc/edison/soc.mk
  and built an image and then ran bvbtool's info_boot_image and
  info_image_hashes commands on the resulting boot.img and system.img
  files and verified that the information was correct. Also ran 'm dist'
  and verified that the boot.img and system.img files in the resulting
  target_files.zip file had similar information.

Change-Id: I08045ed8b0cbddc7c3acdd3a6f2c4bb75cb44bbc
2016-03-18 15:25:43 -04:00
Sami Tolvanen
a8c37be285 Revert "Revert "build: pass version and patch level to mkbootimg""
This reverts commit 494a9090f9.

Bug: 27498078
Bug: 22914603
Change-Id: Iee6a784271ec32c6bfcc0a6ad3f0395d82016df3
(cherry picked from commit 3303d909a1)
2016-03-15 11:23:56 -07:00
Sami Tolvanen
3303d909a1 Revert "Revert "build: pass version and patch level to mkbootimg""
This reverts commit 494a9090f9.

Bug: 27498078
Bug: 22914603
Change-Id: Iee6a784271ec32c6bfcc0a6ad3f0395d82016df3
2016-03-15 16:49:30 +00:00
Sami Tolvanen
1bca9fb6d4 Revert "build: pass version and patch level to mkbootimg"
This reverts commit e555f77962.

Bug: 27580174
Change-Id: I0fd1ddb64d2fd4f91b0ecbc1ab8953a1324a10eb
2016-03-14 15:47:11 +00:00
Sami Tolvanen
494a9090f9 Revert "build: pass version and patch level to mkbootimg"
This reverts commit 8fb47f191f.

Bug: 27580174
Change-Id: Id87fd1e8da217438757d5a0fa4bbef7aea6770fc
2016-03-11 00:08:57 +00:00
Sami Tolvanen
e555f77962 build: pass version and patch level to mkbootimg
Add --os_version and --os_patch_level arguments to mkbootimg.

Needs matching changes from
  I57682611e0c27fec5ed284da7d9a788383ff98b1

Bug: 27498078
Bug: 22914603
Change-Id: I04e20b0de40d864aac92ac7bcf466a6cbde3d0e4
(cherry pick from commit 8fb47f191f)
2016-03-08 08:21:52 -08:00
Sami Tolvanen
8fb47f191f build: pass version and patch level to mkbootimg
Add --os_version and --os_patch_level arguments to mkbootimg.

Needs matching changes from
  I57682611e0c27fec5ed284da7d9a788383ff98b1

Bug: 27498078
Bug: 22914603
Change-Id: I04e20b0de40d864aac92ac7bcf466a6cbde3d0e4
2016-03-07 11:55:22 -08:00
Alex Klyubin
b05b62df2e Sign APKs using SHA-256 instead of SHA-1 when possible.
This changes the build system to provide the signapk tool with the
minSdkVersion of the APK being signed. signapk in turn will then use
SHA-256 instead of SHA-1 if minSdkVersion is 18 (JB MR2) or higher
(see c2c49ed0c1).

To avoid increasing incremental OTA update package sizes for already
released platforms, release build scripts disable the above logic when
signing target files ZIPs for pre-N platforms.

Bug: 25643280

(cherry picked from commit 2cfd1d108c)

Change-Id: I38450d07ddc05c705de40313f843beada8db7d98
2016-02-10 17:19:08 -08:00
Alex Klyubin
2cfd1d108c Sign APKs using SHA-256 instead of SHA-1 when possible.
This changes the build system to provide the signapk tool with the
minSdkVersion of the APK being signed. signapk in turn will then use
SHA-256 instead of SHA-1 if minSdkVersion is 18 (JB MR2) or higher
(see c2c49ed0c1).

To avoid increasing incremental OTA update package sizes for already
released platforms, release build scripts disable the above logic when
signing target files ZIPs for pre-N platforms.

Bug: 25643280

Change-Id: I3f2faaf49c6fa392ffbf1ee9f30de476f9f73231
2016-02-10 09:40:31 -08:00
Tao Bao
b4cfca530c releasetools: Add two new entries to metadata.
Add "ota-required-cache" into the metadata file in an OTA package,
which shows the minimum free space on /cache to apply the update.

Add "ota-type" into the metadata file, which shows the OTA type for
this package (i.e. one of FILE, BLOCK and AB).

Also add the cache free space check into updater-script when generating
block-based incremental OTAs (we only had such lines for file-based
incrementals before).

Bug: 26731903
Change-Id: Id6ff0fc4cdfb1443636b0b3800b0f8bddb5bb1d0
(cherry picked from commit d8d14bec0d)
2016-02-10 09:37:40 -08:00
Tao Bao
d8d14bec0d releasetools: Add two new entries to metadata.
Add "ota-required-cache" into the metadata file in an OTA package,
which shows the minimum free space on /cache to apply the update.

Add "ota-type" into the metadata file, which shows the OTA type for
this package (i.e. one of FILE, BLOCK and AB).

Also add the cache free space check into updater-script when generating
block-based incremental OTAs (we only had such lines for file-based
incrementals before).

Bug: 26731903
Change-Id: Id6ff0fc4cdfb1443636b0b3800b0f8bddb5bb1d0
2016-02-08 11:00:27 -08:00
Alex Klyubin
061289c432 Revert "Sign APKs using SHA-256 instead of SHA-1 when possible." This is breaking CTS.
This reverts commit c2a36afd67.

Change-Id: I4389bf99aeb213198c1c501ba9462bd4a4540d0a
2016-01-29 23:56:44 +00:00
Alex Klyubin
c2a36afd67 Sign APKs using SHA-256 instead of SHA-1 when possible.
This changes the build system to provide the signapk tool with the
minSdkVersion of the APK being signed. signapk in turn will then use
SHA-256 instead of SHA-1 if minSdkVersion is 18 (JB MR2) or higher
(see c2c49ed0c1).

To avoid increasing incremental OTA update package sizes for already
released platforms, release build scripts disable the above logic when
signing target files ZIPs for pre-N platforms.

Bug: 25643280

(cherry picked from commit de5bc04717)

Change-Id: I4b100750e47788ab6ed897a0a5abfd33542e8676
2016-01-29 10:17:02 -08:00