Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2008 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 17 | #include "applypatch/applypatch.h" |
| 18 | |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 19 | #include <errno.h> |
Tao Bao | ba9a42a | 2015-06-23 23:23:33 -0700 | [diff] [blame] | 20 | #include <fcntl.h> |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 21 | #include <libgen.h> |
| 22 | #include <stdio.h> |
| 23 | #include <stdlib.h> |
| 24 | #include <string.h> |
| 25 | #include <sys/stat.h> |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 26 | #include <sys/types.h> |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 27 | #include <unistd.h> |
| 28 | |
Tianjie Xu | 22f1120 | 2018-08-27 10:50:31 -0700 | [diff] [blame] | 29 | #include <algorithm> |
Tao Bao | c0e1c46 | 2017-02-01 10:20:10 -0800 | [diff] [blame] | 30 | #include <functional> |
Yabin Cui | d483c20 | 2016-02-03 17:08:52 -0800 | [diff] [blame] | 31 | #include <memory> |
| 32 | #include <string> |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 33 | #include <utility> |
| 34 | #include <vector> |
Yabin Cui | d483c20 | 2016-02-03 17:08:52 -0800 | [diff] [blame] | 35 | |
Tianjie Xu | 22f1120 | 2018-08-27 10:50:31 -0700 | [diff] [blame] | 36 | #include <android-base/file.h> |
Tao Bao | 40e144d | 2017-03-15 01:10:58 -0700 | [diff] [blame] | 37 | #include <android-base/logging.h> |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 38 | #include <android-base/parseint.h> |
Elliott Hughes | 4b166f0 | 2015-12-04 15:30:20 -0800 | [diff] [blame] | 39 | #include <android-base/strings.h> |
Tianjie Xu | 22f1120 | 2018-08-27 10:50:31 -0700 | [diff] [blame] | 40 | #include <android-base/unique_fd.h> |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 41 | #include <openssl/sha.h> |
Tao Bao | aca8e89 | 2015-07-17 11:47:44 -0700 | [diff] [blame] | 42 | |
Conn O'Griofa | d920104 | 2014-03-25 01:26:49 +0000 | [diff] [blame] | 43 | #include "bmlutils/bmlutils.h" |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 44 | #include "mtdutils/mtdutils.h" |
Ethan Yonker | 8373cfe | 2017-09-08 06:50:54 -0500 | [diff] [blame] | 45 | |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 46 | #include "edify/expr.h" |
Tao Bao | 641fa97 | 2018-04-25 18:59:40 -0700 | [diff] [blame] | 47 | #include "otautil/paths.h" |
Tao Bao | 09e468f | 2017-09-29 14:39:33 -0700 | [diff] [blame] | 48 | #include "otautil/print_sha1.h" |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 49 | |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 50 | using namespace std::string_literals; |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 51 | |
bigbiff | 26d5d5f | 2020-03-23 09:56:16 -0400 | [diff] [blame^] | 52 | <<<<<<< HEAD |
Tao Bao | aca8e89 | 2015-07-17 11:47:44 -0700 | [diff] [blame] | 53 | static bool mtd_partitions_scanned = false; |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 54 | |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 55 | // Read a file into memory; store the file contents and associated metadata in *file. |
Hristo Bojinov | db314d6 | 2010-08-02 10:29:49 -0700 | [diff] [blame] | 56 | // Return 0 on success. |
Doug Zongker | a1bc148 | 2014-02-13 15:18:19 -0800 | [diff] [blame] | 57 | int LoadFileContents(const char* filename, FileContents* file) { |
Ethan Yonker | 8373cfe | 2017-09-08 06:50:54 -0500 | [diff] [blame] | 58 | // A special 'filename' beginning with "MTD:" or "EMMC:" means to |
| 59 | // load the contents of a partition. |
| 60 | if (strncmp(filename, "MTD:", 4) == 0 || |
| 61 | strncmp(filename, "EMMC:", 5) == 0 || |
| 62 | strncmp(filename, "BML:", 4) == 0) { |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 63 | return LoadPartitionContents(filename, file); |
| 64 | } |
bigbiff | 26d5d5f | 2020-03-23 09:56:16 -0400 | [diff] [blame^] | 65 | ======= |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 66 | static bool GenerateTarget(const Partition& target, const FileContents& source_file, |
| 67 | const Value& patch, const Value* bonus_data); |
bigbiff | 26d5d5f | 2020-03-23 09:56:16 -0400 | [diff] [blame^] | 68 | >>>>>>> android-10.0.0_r25 |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 69 | |
Tao Bao | 09e8493 | 2018-08-31 11:25:05 -0700 | [diff] [blame] | 70 | bool LoadFileContents(const std::string& filename, FileContents* file) { |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 71 | // No longer allow loading contents from eMMC partitions. |
Tao Bao | 8dc7049 | 2018-06-20 10:14:40 -0700 | [diff] [blame] | 72 | if (android::base::StartsWith(filename, "EMMC:")) { |
Tao Bao | 09e8493 | 2018-08-31 11:25:05 -0700 | [diff] [blame] | 73 | return false; |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 74 | } |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 75 | |
Tianjie Xu | 22f1120 | 2018-08-27 10:50:31 -0700 | [diff] [blame] | 76 | std::string data; |
| 77 | if (!android::base::ReadFileToString(filename, &data)) { |
| 78 | PLOG(ERROR) << "Failed to read \"" << filename << "\""; |
Tao Bao | 09e8493 | 2018-08-31 11:25:05 -0700 | [diff] [blame] | 79 | return false; |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 80 | } |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 81 | |
Tianjie Xu | 22f1120 | 2018-08-27 10:50:31 -0700 | [diff] [blame] | 82 | file->data = std::vector<unsigned char>(data.begin(), data.end()); |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 83 | SHA1(file->data.data(), file->data.size(), file->sha1); |
Tao Bao | 09e8493 | 2018-08-31 11:25:05 -0700 | [diff] [blame] | 84 | return true; |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 85 | } |
| 86 | |
bigbiff | 26d5d5f | 2020-03-23 09:56:16 -0400 | [diff] [blame^] | 87 | <<<<<<< HEAD |
Elliott Hughes | 63a3192 | 2016-06-09 17:41:22 -0700 | [diff] [blame] | 88 | // Load the contents of an EMMC partition into the provided |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 89 | // FileContents. filename should be a string of the form |
Elliott Hughes | 63a3192 | 2016-06-09 17:41:22 -0700 | [diff] [blame] | 90 | // "EMMC:<partition_device>:...". The smallest size_n bytes for |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 91 | // which that prefix of the partition contents has the corresponding |
| 92 | // sha1 hash will be loaded. It is acceptable for a size value to be |
| 93 | // repeated with different sha1s. Will return 0 on success. |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 94 | // |
| 95 | // This complexity is needed because if an OTA installation is |
| 96 | // interrupted, the partition might contain either the source or the |
| 97 | // target data, which might be of different lengths. We need to know |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 98 | // the length in order to read from a partition (there is no |
| 99 | // "end-of-file" marker), so the caller must specify the possible |
| 100 | // lengths and the hash of the data, and we'll do the load expecting |
| 101 | // to find one of those hashes. |
| 102 | enum PartitionType { MTD, EMMC }; |
| 103 | |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 104 | static int LoadPartitionContents(const std::string& filename, FileContents* file) { |
| 105 | std::vector<std::string> pieces = android::base::Split(filename, ":"); |
Ethan Yonker | 8373cfe | 2017-09-08 06:50:54 -0500 | [diff] [blame] | 106 | if (pieces.size() < 4 || pieces.size() % 2 != 0) { |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 107 | printf("LoadPartitionContents called with bad filename \"%s\"\n", filename.c_str()); |
| 108 | return -1; |
| 109 | } |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 110 | |
Ethan Yonker | 8373cfe | 2017-09-08 06:50:54 -0500 | [diff] [blame] | 111 | enum PartitionType type; |
| 112 | if (pieces[0] == "MTD") { |
| 113 | type = MTD; |
| 114 | } else if (pieces[0] == "EMMC") { |
| 115 | type = EMMC; |
| 116 | } else if (pieces[0] == "BML") { |
| 117 | type = EMMC; |
| 118 | } else { |
| 119 | printf("LoadPartitionContents called with bad filename (%s)\n", filename.c_str()); |
| 120 | return -1; |
| 121 | } |
| 122 | |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 123 | size_t pair_count = (pieces.size() - 2) / 2; // # of (size, sha1) pairs in filename |
| 124 | std::vector<std::pair<size_t, std::string>> pairs; |
| 125 | for (size_t i = 0; i < pair_count; ++i) { |
| 126 | size_t size; |
| 127 | if (!android::base::ParseUint(pieces[i * 2 + 2], &size) || size == 0) { |
| 128 | printf("LoadPartitionContents called with bad size \"%s\"\n", pieces[i * 2 + 2].c_str()); |
| 129 | return -1; |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 130 | } |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 131 | pairs.push_back({ size, pieces[i * 2 + 3] }); |
| 132 | } |
| 133 | |
| 134 | // Sort the pairs array so that they are in order of increasing size. |
| 135 | std::sort(pairs.begin(), pairs.end()); |
| 136 | |
| 137 | const char* partition = pieces[1].c_str(); |
Tao Bao | 358c2ec | 2016-11-28 11:48:43 -0800 | [diff] [blame] | 138 | unique_file dev(ota_fopen(partition, "rb")); |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 139 | if (!dev) { |
| 140 | printf("failed to open emmc partition \"%s\": %s\n", partition, strerror(errno)); |
| 141 | return -1; |
bigbiff | 26d5d5f | 2020-03-23 09:56:16 -0400 | [diff] [blame^] | 142 | ======= |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 143 | // Reads the contents of a Partition to the given FileContents buffer. |
| 144 | static bool ReadPartitionToBuffer(const Partition& partition, FileContents* out, |
| 145 | bool check_backup) { |
| 146 | uint8_t expected_sha1[SHA_DIGEST_LENGTH]; |
| 147 | if (ParseSha1(partition.hash, expected_sha1) != 0) { |
| 148 | LOG(ERROR) << "Failed to parse target hash \"" << partition.hash << "\""; |
| 149 | return false; |
bigbiff | 26d5d5f | 2020-03-23 09:56:16 -0400 | [diff] [blame^] | 150 | >>>>>>> android-10.0.0_r25 |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 151 | } |
| 152 | |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 153 | android::base::unique_fd dev(open(partition.name.c_str(), O_RDONLY)); |
Bernie Innocenti | 8bd6f45 | 2019-03-28 15:48:08 +0900 | [diff] [blame] | 154 | if (dev == -1) { |
Tao Bao | 859bfc5 | 2018-04-25 23:00:27 -0700 | [diff] [blame] | 155 | PLOG(ERROR) << "Failed to open eMMC partition \"" << partition << "\""; |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 156 | } else { |
| 157 | std::vector<unsigned char> buffer(partition.size); |
| 158 | if (!android::base::ReadFully(dev, buffer.data(), buffer.size())) { |
| 159 | PLOG(ERROR) << "Failed to read " << buffer.size() << " bytes of data for partition " |
| 160 | << partition; |
| 161 | } else { |
| 162 | SHA1(buffer.data(), buffer.size(), out->sha1); |
| 163 | if (memcmp(out->sha1, expected_sha1, SHA_DIGEST_LENGTH) == 0) { |
| 164 | out->data = std::move(buffer); |
| 165 | return true; |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 166 | } |
bigbiff | 26d5d5f | 2020-03-23 09:56:16 -0400 | [diff] [blame^] | 167 | <<<<<<< HEAD |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 168 | SHA1_Update(&sha_ctx, buffer_ptr, read); |
| 169 | buffer_size += read; |
| 170 | buffer_ptr += read; |
Tao Bao | aca8e89 | 2015-07-17 11:47:44 -0700 | [diff] [blame] | 171 | } |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 172 | |
Ethan Yonker | b8e985c | 2016-08-31 13:42:11 -0500 | [diff] [blame] | 173 | if (pieces[0] == "BML") { |
Ethan Yonker | 8373cfe | 2017-09-08 06:50:54 -0500 | [diff] [blame] | 174 | if (strcmp(partition, "boot") == 0) { |
| 175 | partition = BOARD_BML_BOOT; |
| 176 | } else if (strcmp(partition, "recovery") == 0) { |
| 177 | partition = BOARD_BML_RECOVERY; |
| 178 | } |
Conn O'Griofa | d920104 | 2014-03-25 01:26:49 +0000 | [diff] [blame] | 179 | } |
| 180 | |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 181 | // Duplicate the SHA context and finalize the duplicate so we can |
| 182 | // check it against this pair's expected hash. |
| 183 | SHA_CTX temp_ctx; |
| 184 | memcpy(&temp_ctx, &sha_ctx, sizeof(SHA_CTX)); |
| 185 | uint8_t sha_so_far[SHA_DIGEST_LENGTH]; |
| 186 | SHA1_Final(sha_so_far, &temp_ctx); |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 187 | |
Sen Jiang | c48cb5e | 2016-02-04 16:23:21 +0800 | [diff] [blame] | 188 | uint8_t parsed_sha[SHA_DIGEST_LENGTH]; |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 189 | if (ParseSha1(current_sha1.c_str(), parsed_sha) != 0) { |
| 190 | printf("failed to parse SHA-1 %s in %s\n", current_sha1.c_str(), filename.c_str()); |
| 191 | return -1; |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 192 | } |
| 193 | |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 194 | if (memcmp(sha_so_far, parsed_sha, SHA_DIGEST_LENGTH) == 0) { |
| 195 | // We have a match. Stop reading the partition; we'll return the data we've read so far. |
| 196 | printf("partition read matched size %zu SHA-1 %s\n", current_size, current_sha1.c_str()); |
| 197 | found = true; |
| 198 | break; |
bigbiff | 26d5d5f | 2020-03-23 09:56:16 -0400 | [diff] [blame^] | 199 | ======= |
| 200 | >>>>>>> android-10.0.0_r25 |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 201 | } |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 202 | } |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 203 | |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 204 | if (!check_backup) { |
| 205 | LOG(ERROR) << "Partition contents don't have the expected checksum"; |
| 206 | return false; |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 207 | } |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 208 | |
Tao Bao | 09e8493 | 2018-08-31 11:25:05 -0700 | [diff] [blame] | 209 | if (LoadFileContents(Paths::Get().cache_temp_source(), out) && |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 210 | memcmp(out->sha1, expected_sha1, SHA_DIGEST_LENGTH) == 0) { |
| 211 | return true; |
| 212 | } |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 213 | |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 214 | LOG(ERROR) << "Both of partition contents and backup don't have the expected checksum"; |
| 215 | return false; |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 216 | } |
| 217 | |
Tao Bao | 09e8493 | 2018-08-31 11:25:05 -0700 | [diff] [blame] | 218 | bool SaveFileContents(const std::string& filename, const FileContents* file) { |
Tianjie Xu | 22f1120 | 2018-08-27 10:50:31 -0700 | [diff] [blame] | 219 | android::base::unique_fd fd( |
| 220 | open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR)); |
Tao Bao | 6e02ea9 | 2016-11-17 11:24:07 -0800 | [diff] [blame] | 221 | if (fd == -1) { |
Tao Bao | 859bfc5 | 2018-04-25 23:00:27 -0700 | [diff] [blame] | 222 | PLOG(ERROR) << "Failed to open \"" << filename << "\" for write"; |
Tao Bao | 09e8493 | 2018-08-31 11:25:05 -0700 | [diff] [blame] | 223 | return false; |
Tao Bao | 6e02ea9 | 2016-11-17 11:24:07 -0800 | [diff] [blame] | 224 | } |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 225 | |
Tianjie Xu | 22f1120 | 2018-08-27 10:50:31 -0700 | [diff] [blame] | 226 | if (!android::base::WriteFully(fd, file->data.data(), file->data.size())) { |
| 227 | PLOG(ERROR) << "Failed to write " << file->data.size() << " bytes of data to " << filename; |
Tao Bao | 09e8493 | 2018-08-31 11:25:05 -0700 | [diff] [blame] | 228 | return false; |
Tao Bao | 6e02ea9 | 2016-11-17 11:24:07 -0800 | [diff] [blame] | 229 | } |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 230 | |
bigbiff | 26d5d5f | 2020-03-23 09:56:16 -0400 | [diff] [blame^] | 231 | <<<<<<< HEAD |
Tao Bao | 6e02ea9 | 2016-11-17 11:24:07 -0800 | [diff] [blame] | 232 | return 0; |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 233 | } |
| 234 | |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 235 | // Write a memory buffer to 'target' partition, a string of the form |
Elliott Hughes | 63a3192 | 2016-06-09 17:41:22 -0700 | [diff] [blame] | 236 | // "EMMC:<partition_device>[:...]". The target name |
Tao Bao | 1ce7a2a | 2015-07-24 15:29:12 -0700 | [diff] [blame] | 237 | // might contain multiple colons, but WriteToPartition() only uses the first |
| 238 | // two and ignores the rest. Return 0 on success. |
Tao Bao | 6e02ea9 | 2016-11-17 11:24:07 -0800 | [diff] [blame] | 239 | int WriteToPartition(const unsigned char* data, size_t len, const std::string& target) { |
Tao Bao | aca8e89 | 2015-07-17 11:47:44 -0700 | [diff] [blame] | 240 | std::string copy(target); |
| 241 | std::vector<std::string> pieces = android::base::Split(copy, ":"); |
| 242 | |
Tao Bao | 1ce7a2a | 2015-07-24 15:29:12 -0700 | [diff] [blame] | 243 | if (pieces.size() < 2) { |
Ethan Yonker | 8373cfe | 2017-09-08 06:50:54 -0500 | [diff] [blame] | 244 | printf("WriteToPartition called with bad target (%s)\n", target.c_str()); |
Tao Bao | aca8e89 | 2015-07-17 11:47:44 -0700 | [diff] [blame] | 245 | return -1; |
| 246 | } |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 247 | |
| 248 | enum PartitionType type; |
Tao Bao | aca8e89 | 2015-07-17 11:47:44 -0700 | [diff] [blame] | 249 | if (pieces[0] == "MTD") { |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 250 | type = MTD; |
Tao Bao | aca8e89 | 2015-07-17 11:47:44 -0700 | [diff] [blame] | 251 | } else if (pieces[0] == "EMMC") { |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 252 | type = EMMC; |
Ethan Yonker | b8e985c | 2016-08-31 13:42:11 -0500 | [diff] [blame] | 253 | } else if (pieces[0] == "BML") { |
Conn O'Griofa | d920104 | 2014-03-25 01:26:49 +0000 | [diff] [blame] | 254 | type = EMMC; |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 255 | } else { |
Ethan Yonker | 8373cfe | 2017-09-08 06:50:54 -0500 | [diff] [blame] | 256 | printf("WriteToPartition called with bad target (%s)\n", target.c_str()); |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 257 | return -1; |
bigbiff | 26d5d5f | 2020-03-23 09:56:16 -0400 | [diff] [blame^] | 258 | ======= |
Tianjie Xu | 22f1120 | 2018-08-27 10:50:31 -0700 | [diff] [blame] | 259 | if (fsync(fd) != 0) { |
Tao Bao | 859bfc5 | 2018-04-25 23:00:27 -0700 | [diff] [blame] | 260 | PLOG(ERROR) << "Failed to fsync \"" << filename << "\""; |
Tao Bao | 09e8493 | 2018-08-31 11:25:05 -0700 | [diff] [blame] | 261 | return false; |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 262 | } |
Tianjie Xu | 22f1120 | 2018-08-27 10:50:31 -0700 | [diff] [blame] | 263 | |
| 264 | if (close(fd.release()) != 0) { |
Tao Bao | 859bfc5 | 2018-04-25 23:00:27 -0700 | [diff] [blame] | 265 | PLOG(ERROR) << "Failed to close \"" << filename << "\""; |
Tao Bao | 09e8493 | 2018-08-31 11:25:05 -0700 | [diff] [blame] | 266 | return false; |
Michael Runge | be81e51 | 2014-10-29 12:42:15 -0700 | [diff] [blame] | 267 | } |
| 268 | |
Tao Bao | 09e8493 | 2018-08-31 11:25:05 -0700 | [diff] [blame] | 269 | return true; |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 270 | } |
| 271 | |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 272 | // Writes a memory buffer to 'target' Partition. |
| 273 | static bool WriteBufferToPartition(const FileContents& file_contents, const Partition& partition) { |
| 274 | const unsigned char* data = file_contents.data.data(); |
| 275 | size_t len = file_contents.data.size(); |
Tao Bao | 6e02ea9 | 2016-11-17 11:24:07 -0800 | [diff] [blame] | 276 | size_t start = 0; |
| 277 | bool success = false; |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 278 | for (size_t attempt = 0; attempt < 2; ++attempt) { |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 279 | android::base::unique_fd fd(open(partition.name.c_str(), O_RDWR)); |
Tianjie Xu | 22f1120 | 2018-08-27 10:50:31 -0700 | [diff] [blame] | 280 | if (fd == -1) { |
| 281 | PLOG(ERROR) << "Failed to open \"" << partition << "\""; |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 282 | return false; |
Tianjie Xu | 22f1120 | 2018-08-27 10:50:31 -0700 | [diff] [blame] | 283 | } |
| 284 | |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 285 | if (TEMP_FAILURE_RETRY(lseek(fd, start, SEEK_SET)) == -1) { |
Tao Bao | 859bfc5 | 2018-04-25 23:00:27 -0700 | [diff] [blame] | 286 | PLOG(ERROR) << "Failed to seek to " << start << " on \"" << partition << "\""; |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 287 | return false; |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 288 | } |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 289 | |
Tianjie Xu | 22f1120 | 2018-08-27 10:50:31 -0700 | [diff] [blame] | 290 | if (!android::base::WriteFully(fd, data + start, len - start)) { |
| 291 | PLOG(ERROR) << "Failed to write " << len - start << " bytes to \"" << partition << "\""; |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 292 | return false; |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 293 | } |
| 294 | |
Tianjie Xu | 22f1120 | 2018-08-27 10:50:31 -0700 | [diff] [blame] | 295 | if (fsync(fd) != 0) { |
Tao Bao | 859bfc5 | 2018-04-25 23:00:27 -0700 | [diff] [blame] | 296 | PLOG(ERROR) << "Failed to sync \"" << partition << "\""; |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 297 | return false; |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 298 | } |
Tianjie Xu | 22f1120 | 2018-08-27 10:50:31 -0700 | [diff] [blame] | 299 | if (close(fd.release()) != 0) { |
Tao Bao | 859bfc5 | 2018-04-25 23:00:27 -0700 | [diff] [blame] | 300 | PLOG(ERROR) << "Failed to close \"" << partition << "\""; |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 301 | return false; |
Elliott Hughes | 63a3192 | 2016-06-09 17:41:22 -0700 | [diff] [blame] | 302 | } |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 303 | |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 304 | fd.reset(open(partition.name.c_str(), O_RDONLY)); |
Tao Bao | 6e02ea9 | 2016-11-17 11:24:07 -0800 | [diff] [blame] | 305 | if (fd == -1) { |
Tao Bao | 859bfc5 | 2018-04-25 23:00:27 -0700 | [diff] [blame] | 306 | PLOG(ERROR) << "Failed to reopen \"" << partition << "\" for verification"; |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 307 | return false; |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 308 | } |
| 309 | |
| 310 | // Drop caches so our subsequent verification read won't just be reading the cache. |
Elliott Hughes | 63a3192 | 2016-06-09 17:41:22 -0700 | [diff] [blame] | 311 | sync(); |
Tianjie Xu | 22f1120 | 2018-08-27 10:50:31 -0700 | [diff] [blame] | 312 | std::string drop_cache = "/proc/sys/vm/drop_caches"; |
| 313 | if (!android::base::WriteStringToFile("3\n", drop_cache)) { |
| 314 | PLOG(ERROR) << "Failed to write to " << drop_cache; |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 315 | } else { |
Tao Bao | 859bfc5 | 2018-04-25 23:00:27 -0700 | [diff] [blame] | 316 | LOG(INFO) << " caches dropped"; |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 317 | } |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 318 | sleep(1); |
Elliott Hughes | 63a3192 | 2016-06-09 17:41:22 -0700 | [diff] [blame] | 319 | |
Tao Bao | 6e02ea9 | 2016-11-17 11:24:07 -0800 | [diff] [blame] | 320 | // Verify. |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 321 | if (TEMP_FAILURE_RETRY(lseek(fd, 0, SEEK_SET)) == -1) { |
Tao Bao | 859bfc5 | 2018-04-25 23:00:27 -0700 | [diff] [blame] | 322 | PLOG(ERROR) << "Failed to seek to 0 on " << partition; |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 323 | return false; |
bigbiff | 26d5d5f | 2020-03-23 09:56:16 -0400 | [diff] [blame^] | 324 | >>>>>>> android-10.0.0_r25 |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 325 | } |
Ethan Yonker | 34ae483 | 2016-08-24 15:32:18 -0500 | [diff] [blame] | 326 | |
Tao Bao | aca8e89 | 2015-07-17 11:47:44 -0700 | [diff] [blame] | 327 | const char* partition = pieces[1].c_str(); |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 328 | |
bigbiff | 26d5d5f | 2020-03-23 09:56:16 -0400 | [diff] [blame^] | 329 | <<<<<<< HEAD |
Ethan Yonker | b8e985c | 2016-08-31 13:42:11 -0500 | [diff] [blame] | 330 | if (pieces[0] == "BML") { |
Conn O'Griofa | d920104 | 2014-03-25 01:26:49 +0000 | [diff] [blame] | 331 | if (strcmp(partition, "boot") == 0) { |
| 332 | partition = BOARD_BML_BOOT; |
| 333 | } else if (strcmp(partition, "recovery") == 0) { |
| 334 | partition = BOARD_BML_RECOVERY; |
| 335 | } |
| 336 | |
| 337 | int bmlpartition = open(partition, O_RDWR | O_LARGEFILE); |
| 338 | if (bmlpartition < 0) |
| 339 | return -1; |
| 340 | if (ioctl(bmlpartition, BML_UNLOCK_ALL, 0)) { |
| 341 | printf("failed to unlock BML partition: (%s)\n", partition); |
| 342 | return -1; |
| 343 | } |
| 344 | close(bmlpartition); |
| 345 | } |
| 346 | |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 347 | if (partition == NULL) { |
Ethan Yonker | 8373cfe | 2017-09-08 06:50:54 -0500 | [diff] [blame] | 348 | printf("bad partition target name \"%s\"\n", target.c_str()); |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 349 | return -1; |
| 350 | } |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 351 | |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 352 | switch (type) { |
Tao Bao | ba9a42a | 2015-06-23 23:23:33 -0700 | [diff] [blame] | 353 | case MTD: { |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 354 | if (!mtd_partitions_scanned) { |
| 355 | mtd_scan_partitions(); |
Tao Bao | aca8e89 | 2015-07-17 11:47:44 -0700 | [diff] [blame] | 356 | mtd_partitions_scanned = true; |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 357 | } |
| 358 | |
| 359 | const MtdPartition* mtd = mtd_find_partition_by_name(partition); |
| 360 | if (mtd == NULL) { |
Tao Bao | ba9a42a | 2015-06-23 23:23:33 -0700 | [diff] [blame] | 361 | printf("mtd partition \"%s\" not found for writing\n", partition); |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 362 | return -1; |
| 363 | } |
| 364 | |
| 365 | MtdWriteContext* ctx = mtd_write_partition(mtd); |
| 366 | if (ctx == NULL) { |
Tao Bao | ba9a42a | 2015-06-23 23:23:33 -0700 | [diff] [blame] | 367 | printf("failed to init mtd partition \"%s\" for writing\n", partition); |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 368 | return -1; |
| 369 | } |
| 370 | |
Yabin Cui | d483c20 | 2016-02-03 17:08:52 -0800 | [diff] [blame] | 371 | size_t written = mtd_write_data(ctx, reinterpret_cast<const char*>(data), len); |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 372 | if (written != len) { |
Tao Bao | ba9a42a | 2015-06-23 23:23:33 -0700 | [diff] [blame] | 373 | printf("only wrote %zu of %zu bytes to MTD %s\n", written, len, partition); |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 374 | mtd_write_close(ctx); |
| 375 | return -1; |
| 376 | } |
| 377 | |
| 378 | if (mtd_erase_blocks(ctx, -1) < 0) { |
| 379 | printf("error finishing mtd write of %s\n", partition); |
| 380 | mtd_write_close(ctx); |
| 381 | return -1; |
| 382 | } |
| 383 | |
| 384 | if (mtd_write_close(ctx)) { |
| 385 | printf("error closing mtd write of %s\n", partition); |
| 386 | return -1; |
| 387 | } |
| 388 | break; |
Tao Bao | ba9a42a | 2015-06-23 23:23:33 -0700 | [diff] [blame] | 389 | } |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 390 | |
Tao Bao | ba9a42a | 2015-06-23 23:23:33 -0700 | [diff] [blame] | 391 | case EMMC: { |
Doug Zongker | 044a0b4 | 2013-07-08 09:42:54 -0700 | [diff] [blame] | 392 | size_t start = 0; |
Tao Bao | ba9a42a | 2015-06-23 23:23:33 -0700 | [diff] [blame] | 393 | bool success = false; |
Ethan Yonker | 8373cfe | 2017-09-08 06:50:54 -0500 | [diff] [blame] | 394 | unique_fd fd(ota_open(partition, O_RDWR | O_SYNC)); |
Doug Zongker | c870a99 | 2013-07-09 10:34:46 -0700 | [diff] [blame] | 395 | if (fd < 0) { |
Doug Zongker | 044a0b4 | 2013-07-08 09:42:54 -0700 | [diff] [blame] | 396 | printf("failed to open %s: %s\n", partition, strerror(errno)); |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 397 | return -1; |
| 398 | } |
Doug Zongker | 044a0b4 | 2013-07-08 09:42:54 -0700 | [diff] [blame] | 399 | |
Tao Bao | aca8e89 | 2015-07-17 11:47:44 -0700 | [diff] [blame] | 400 | for (size_t attempt = 0; attempt < 2; ++attempt) { |
Elliott Hughes | 2f5feed | 2015-04-28 17:24:24 -0700 | [diff] [blame] | 401 | if (TEMP_FAILURE_RETRY(lseek(fd, start, SEEK_SET)) == -1) { |
Tao Bao | ba9a42a | 2015-06-23 23:23:33 -0700 | [diff] [blame] | 402 | printf("failed seek on %s: %s\n", partition, strerror(errno)); |
Elliott Hughes | 2f5feed | 2015-04-28 17:24:24 -0700 | [diff] [blame] | 403 | return -1; |
| 404 | } |
Doug Zongker | 044a0b4 | 2013-07-08 09:42:54 -0700 | [diff] [blame] | 405 | while (start < len) { |
| 406 | size_t to_write = len - start; |
Doug Zongker | 168724c | 2013-12-19 15:16:57 -0800 | [diff] [blame] | 407 | if (to_write > 1<<20) to_write = 1<<20; |
Doug Zongker | 044a0b4 | 2013-07-08 09:42:54 -0700 | [diff] [blame] | 408 | |
Jed Estep | f1fc48c | 2015-12-15 16:04:53 -0800 | [diff] [blame] | 409 | ssize_t written = TEMP_FAILURE_RETRY(ota_write(fd, data+start, to_write)); |
Elliott Hughes | 2f5feed | 2015-04-28 17:24:24 -0700 | [diff] [blame] | 410 | if (written == -1) { |
| 411 | printf("failed write writing to %s: %s\n", partition, strerror(errno)); |
| 412 | return -1; |
Doug Zongker | 044a0b4 | 2013-07-08 09:42:54 -0700 | [diff] [blame] | 413 | } |
Doug Zongker | c870a99 | 2013-07-09 10:34:46 -0700 | [diff] [blame] | 414 | start += written; |
Doug Zongker | 044a0b4 | 2013-07-08 09:42:54 -0700 | [diff] [blame] | 415 | } |
Jed Estep | f1fc48c | 2015-12-15 16:04:53 -0800 | [diff] [blame] | 416 | if (ota_fsync(fd) != 0) { |
Tao Bao | ba9a42a | 2015-06-23 23:23:33 -0700 | [diff] [blame] | 417 | printf("failed to sync to %s (%s)\n", partition, strerror(errno)); |
Michael Runge | cddb68b | 2014-10-29 12:42:15 -0700 | [diff] [blame] | 418 | return -1; |
| 419 | } |
Jed Estep | f1fc48c | 2015-12-15 16:04:53 -0800 | [diff] [blame] | 420 | if (ota_close(fd) != 0) { |
Tao Bao | ba9a42a | 2015-06-23 23:23:33 -0700 | [diff] [blame] | 421 | printf("failed to close %s (%s)\n", partition, strerror(errno)); |
Michael Runge | cddb68b | 2014-10-29 12:42:15 -0700 | [diff] [blame] | 422 | return -1; |
| 423 | } |
Ethan Yonker | 8373cfe | 2017-09-08 06:50:54 -0500 | [diff] [blame] | 424 | unique_fd fd(ota_open(partition, O_RDONLY)); |
Michael Runge | cddb68b | 2014-10-29 12:42:15 -0700 | [diff] [blame] | 425 | if (fd < 0) { |
Tao Bao | ba9a42a | 2015-06-23 23:23:33 -0700 | [diff] [blame] | 426 | printf("failed to reopen %s for verify (%s)\n", partition, strerror(errno)); |
Michael Runge | cddb68b | 2014-10-29 12:42:15 -0700 | [diff] [blame] | 427 | return -1; |
| 428 | } |
Doug Zongker | 044a0b4 | 2013-07-08 09:42:54 -0700 | [diff] [blame] | 429 | |
Tao Bao | ba9a42a | 2015-06-23 23:23:33 -0700 | [diff] [blame] | 430 | // Drop caches so our subsequent verification read |
Doug Zongker | 044a0b4 | 2013-07-08 09:42:54 -0700 | [diff] [blame] | 431 | // won't just be reading the cache. |
| 432 | sync(); |
Ethan Yonker | 8373cfe | 2017-09-08 06:50:54 -0500 | [diff] [blame] | 433 | unique_fd dc(ota_open("/proc/sys/vm/drop_caches", O_WRONLY)); |
Jed Estep | f1fc48c | 2015-12-15 16:04:53 -0800 | [diff] [blame] | 434 | if (TEMP_FAILURE_RETRY(ota_write(dc, "3\n", 2)) == -1) { |
Elliott Hughes | 2f5feed | 2015-04-28 17:24:24 -0700 | [diff] [blame] | 435 | printf("write to /proc/sys/vm/drop_caches failed: %s\n", strerror(errno)); |
| 436 | } else { |
| 437 | printf(" caches dropped\n"); |
| 438 | } |
Jed Estep | f1fc48c | 2015-12-15 16:04:53 -0800 | [diff] [blame] | 439 | ota_close(dc); |
Doug Zongker | 044a0b4 | 2013-07-08 09:42:54 -0700 | [diff] [blame] | 440 | sleep(1); |
Doug Zongker | 044a0b4 | 2013-07-08 09:42:54 -0700 | [diff] [blame] | 441 | |
| 442 | // verify |
Elliott Hughes | 2f5feed | 2015-04-28 17:24:24 -0700 | [diff] [blame] | 443 | if (TEMP_FAILURE_RETRY(lseek(fd, 0, SEEK_SET)) == -1) { |
| 444 | printf("failed to seek back to beginning of %s: %s\n", |
| 445 | partition, strerror(errno)); |
| 446 | return -1; |
| 447 | } |
Doug Zongker | 044a0b4 | 2013-07-08 09:42:54 -0700 | [diff] [blame] | 448 | unsigned char buffer[4096]; |
| 449 | start = len; |
Tao Bao | ba9a42a | 2015-06-23 23:23:33 -0700 | [diff] [blame] | 450 | for (size_t p = 0; p < len; p += sizeof(buffer)) { |
Doug Zongker | 044a0b4 | 2013-07-08 09:42:54 -0700 | [diff] [blame] | 451 | size_t to_read = len - p; |
Tao Bao | ba9a42a | 2015-06-23 23:23:33 -0700 | [diff] [blame] | 452 | if (to_read > sizeof(buffer)) { |
| 453 | to_read = sizeof(buffer); |
| 454 | } |
Doug Zongker | 044a0b4 | 2013-07-08 09:42:54 -0700 | [diff] [blame] | 455 | |
Doug Zongker | c870a99 | 2013-07-09 10:34:46 -0700 | [diff] [blame] | 456 | size_t so_far = 0; |
| 457 | while (so_far < to_read) { |
Elliott Hughes | 2f5feed | 2015-04-28 17:24:24 -0700 | [diff] [blame] | 458 | ssize_t read_count = |
Jed Estep | f1fc48c | 2015-12-15 16:04:53 -0800 | [diff] [blame] | 459 | TEMP_FAILURE_RETRY(ota_read(fd, buffer+so_far, to_read-so_far)); |
Elliott Hughes | 2f5feed | 2015-04-28 17:24:24 -0700 | [diff] [blame] | 460 | if (read_count == -1) { |
| 461 | printf("verify read error %s at %zu: %s\n", |
| 462 | partition, p, strerror(errno)); |
| 463 | return -1; |
Doug Zongker | c870a99 | 2013-07-09 10:34:46 -0700 | [diff] [blame] | 464 | } |
Tao Bao | ba9a42a | 2015-06-23 23:23:33 -0700 | [diff] [blame] | 465 | if (static_cast<size_t>(read_count) < to_read) { |
Mark Salyzyn | f3bb31c | 2014-03-14 09:39:48 -0700 | [diff] [blame] | 466 | printf("short verify read %s at %zu: %zd %zu %s\n", |
Doug Zongker | c870a99 | 2013-07-09 10:34:46 -0700 | [diff] [blame] | 467 | partition, p, read_count, to_read, strerror(errno)); |
| 468 | } |
| 469 | so_far += read_count; |
Doug Zongker | 044a0b4 | 2013-07-08 09:42:54 -0700 | [diff] [blame] | 470 | } |
| 471 | |
Tao Bao | ba9a42a | 2015-06-23 23:23:33 -0700 | [diff] [blame] | 472 | if (memcmp(buffer, data+p, to_read) != 0) { |
Mark Salyzyn | f3bb31c | 2014-03-14 09:39:48 -0700 | [diff] [blame] | 473 | printf("verification failed starting at %zu\n", p); |
Doug Zongker | 044a0b4 | 2013-07-08 09:42:54 -0700 | [diff] [blame] | 474 | start = p; |
| 475 | break; |
| 476 | } |
| 477 | } |
| 478 | |
| 479 | if (start == len) { |
Tao Bao | abba55b | 2015-07-17 18:11:12 -0700 | [diff] [blame] | 480 | printf("verification read succeeded (attempt %zu)\n", attempt+1); |
Doug Zongker | 044a0b4 | 2013-07-08 09:42:54 -0700 | [diff] [blame] | 481 | success = true; |
| 482 | break; |
| 483 | } |
| 484 | } |
| 485 | |
| 486 | if (!success) { |
| 487 | printf("failed to verify after all attempts\n"); |
| 488 | return -1; |
| 489 | } |
| 490 | |
Jed Estep | f1fc48c | 2015-12-15 16:04:53 -0800 | [diff] [blame] | 491 | if (ota_close(fd) != 0) { |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 492 | printf("error closing %s (%s)\n", partition, strerror(errno)); |
| 493 | return -1; |
| 494 | } |
Doug Zongker | bf4a69a | 2013-07-10 13:39:50 -0700 | [diff] [blame] | 495 | sync(); |
Doug Zongker | f291d85 | 2010-07-07 13:55:25 -0700 | [diff] [blame] | 496 | break; |
Doug Zongker | 044a0b4 | 2013-07-08 09:42:54 -0700 | [diff] [blame] | 497 | } |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 498 | } |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 499 | |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 500 | return 0; |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 501 | } |
| 502 | |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 503 | // Take a string 'str' of 40 hex digits and parse it into the 20 |
| 504 | // byte array 'digest'. 'str' may contain only the digest or be of |
| 505 | // the form "<digest>:<anything>". Return 0 on success, -1 on any |
| 506 | // error. |
| 507 | int ParseSha1(const char* str, uint8_t* digest) { |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 508 | const char* ps = str; |
| 509 | uint8_t* pd = digest; |
Sen Jiang | c48cb5e | 2016-02-04 16:23:21 +0800 | [diff] [blame] | 510 | for (int i = 0; i < SHA_DIGEST_LENGTH * 2; ++i, ++ps) { |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 511 | int digit; |
| 512 | if (*ps >= '0' && *ps <= '9') { |
| 513 | digit = *ps - '0'; |
| 514 | } else if (*ps >= 'a' && *ps <= 'f') { |
| 515 | digit = *ps - 'a' + 10; |
| 516 | } else if (*ps >= 'A' && *ps <= 'F') { |
| 517 | digit = *ps - 'A' + 10; |
| 518 | } else { |
| 519 | return -1; |
| 520 | } |
| 521 | if (i % 2 == 0) { |
| 522 | *pd = digit << 4; |
| 523 | } else { |
| 524 | *pd |= digit; |
| 525 | ++pd; |
| 526 | } |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 527 | } |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 528 | if (*ps != '\0') return -1; |
| 529 | return 0; |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 530 | } |
| 531 | |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 532 | // Search an array of sha1 strings for one matching the given sha1. |
| 533 | // Return the index of the match on success, or -1 if no match is |
| 534 | // found. |
Tao Bao | c8e7934 | 2016-12-28 10:11:22 -0800 | [diff] [blame] | 535 | static int FindMatchingPatch(uint8_t* sha1, const std::vector<std::string>& patch_sha1_str) { |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 536 | for (size_t i = 0; i < patch_sha1_str.size(); ++i) { |
Sen Jiang | c48cb5e | 2016-02-04 16:23:21 +0800 | [diff] [blame] | 537 | uint8_t patch_sha1[SHA_DIGEST_LENGTH]; |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 538 | if (ParseSha1(patch_sha1_str[i].c_str(), patch_sha1) == 0 && |
| 539 | memcmp(patch_sha1, sha1, SHA_DIGEST_LENGTH) == 0) { |
| 540 | return i; |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 541 | } |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 542 | } |
| 543 | return -1; |
bigbiff | 26d5d5f | 2020-03-23 09:56:16 -0400 | [diff] [blame^] | 544 | ======= |
Tianjie Xu | 22f1120 | 2018-08-27 10:50:31 -0700 | [diff] [blame] | 545 | if (!android::base::ReadFully(fd, buffer, to_read)) { |
| 546 | PLOG(ERROR) << "Failed to verify-read " << partition << " at " << p; |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 547 | return false; |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 548 | } |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 549 | |
Hristo Bojinov | db314d6 | 2010-08-02 10:29:49 -0700 | [diff] [blame] | 550 | if (memcmp(buffer, data + p, to_read) != 0) { |
Tao Bao | 859bfc5 | 2018-04-25 23:00:27 -0700 | [diff] [blame] | 551 | LOG(ERROR) << "Verification failed starting at " << p; |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 552 | start = p; |
| 553 | break; |
| 554 | } |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 555 | } |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 556 | |
Jed Estep | a7b9a46 | 2015-12-15 16:04:53 -0800 | [diff] [blame] | 557 | if (start == len) { |
Tao Bao | 859bfc5 | 2018-04-25 23:00:27 -0700 | [diff] [blame] | 558 | LOG(INFO) << "Verification read succeeded (attempt " << attempt + 1 << ")"; |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 559 | success = true; |
| 560 | break; |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 561 | } |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 562 | |
Tianjie Xu | 22f1120 | 2018-08-27 10:50:31 -0700 | [diff] [blame] | 563 | if (close(fd.release()) != 0) { |
Tao Bao | 859bfc5 | 2018-04-25 23:00:27 -0700 | [diff] [blame] | 564 | PLOG(ERROR) << "Failed to close " << partition; |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 565 | return false; |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 566 | } |
| 567 | } |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 568 | |
| 569 | if (!success) { |
Tao Bao | 859bfc5 | 2018-04-25 23:00:27 -0700 | [diff] [blame] | 570 | LOG(ERROR) << "Failed to verify after all attempts"; |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 571 | return false; |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 572 | } |
| 573 | |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 574 | sync(); |
| 575 | |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 576 | return true; |
bigbiff | 26d5d5f | 2020-03-23 09:56:16 -0400 | [diff] [blame^] | 577 | >>>>>>> android-10.0.0_r25 |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 578 | } |
Tao Bao | ba9a42a | 2015-06-23 23:23:33 -0700 | [diff] [blame] | 579 | |
Tao Bao | 8dc7049 | 2018-06-20 10:14:40 -0700 | [diff] [blame] | 580 | int ParseSha1(const std::string& str, uint8_t* digest) { |
| 581 | const char* ps = str.c_str(); |
Tao Bao | 155771b | 2018-06-05 11:26:01 -0700 | [diff] [blame] | 582 | uint8_t* pd = digest; |
| 583 | for (int i = 0; i < SHA_DIGEST_LENGTH * 2; ++i, ++ps) { |
| 584 | int digit; |
| 585 | if (*ps >= '0' && *ps <= '9') { |
| 586 | digit = *ps - '0'; |
| 587 | } else if (*ps >= 'a' && *ps <= 'f') { |
| 588 | digit = *ps - 'a' + 10; |
| 589 | } else if (*ps >= 'A' && *ps <= 'F') { |
| 590 | digit = *ps - 'A' + 10; |
| 591 | } else { |
| 592 | return -1; |
Tianjie Xu | aced5d9 | 2016-10-12 10:55:04 -0700 | [diff] [blame] | 593 | } |
Tao Bao | 155771b | 2018-06-05 11:26:01 -0700 | [diff] [blame] | 594 | if (i % 2 == 0) { |
| 595 | *pd = digit << 4; |
| 596 | } else { |
| 597 | *pd |= digit; |
| 598 | ++pd; |
| 599 | } |
| 600 | } |
| 601 | if (*ps != '\0') return -1; |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 602 | return 0; |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 603 | } |
| 604 | |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 605 | bool PatchPartitionCheck(const Partition& target, const Partition& source) { |
| 606 | FileContents target_file; |
| 607 | FileContents source_file; |
| 608 | return (ReadPartitionToBuffer(target, &target_file, false) || |
| 609 | ReadPartitionToBuffer(source, &source_file, true)); |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 610 | } |
| 611 | |
| 612 | int ShowLicenses() { |
Tao Bao | 155771b | 2018-06-05 11:26:01 -0700 | [diff] [blame] | 613 | ShowBSDiffLicense(); |
Tao Bao | 6e02ea9 | 2016-11-17 11:24:07 -0800 | [diff] [blame] | 614 | return 0; |
Doug Zongker | 1c43c97 | 2012-02-28 11:07:09 -0800 | [diff] [blame] | 615 | } |
| 616 | |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 617 | bool PatchPartition(const Partition& target, const Partition& source, const Value& patch, |
| 618 | const Value* bonus) { |
| 619 | LOG(INFO) << "Patching " << target.name; |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 620 | |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 621 | // We try to load and check against the target hash first. |
| 622 | FileContents target_file; |
| 623 | if (ReadPartitionToBuffer(target, &target_file, false)) { |
| 624 | // The early-exit case: the patch was already applied, this file has the desired hash, nothing |
| 625 | // for us to do. |
| 626 | LOG(INFO) << " already " << target.hash.substr(0, 8); |
| 627 | return true; |
Tao Bao | 6e02ea9 | 2016-11-17 11:24:07 -0800 | [diff] [blame] | 628 | } |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 629 | |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 630 | FileContents source_file; |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 631 | if (ReadPartitionToBuffer(source, &source_file, true)) { |
| 632 | return GenerateTarget(target, source_file, patch, bonus); |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 633 | } |
| 634 | |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 635 | LOG(ERROR) << "Failed to find any match"; |
| 636 | return false; |
Tao Bao | abba55b | 2015-07-17 18:11:12 -0700 | [diff] [blame] | 637 | } |
| 638 | |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 639 | bool FlashPartition(const Partition& partition, const std::string& source_filename) { |
| 640 | LOG(INFO) << "Flashing " << partition; |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 641 | |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 642 | // We try to load and check against the target hash first. |
| 643 | FileContents target_file; |
| 644 | if (ReadPartitionToBuffer(partition, &target_file, false)) { |
| 645 | // The early-exit case: the patch was already applied, this file has the desired hash, nothing |
| 646 | // for us to do. |
| 647 | LOG(INFO) << " already " << partition.hash.substr(0, 8); |
| 648 | return true; |
Tao Bao | 8fce75a | 2016-11-10 12:33:41 -0800 | [diff] [blame] | 649 | } |
Tao Bao | abba55b | 2015-07-17 18:11:12 -0700 | [diff] [blame] | 650 | |
Yabin Cui | d6c93af | 2016-02-10 16:41:10 -0800 | [diff] [blame] | 651 | FileContents source_file; |
Tao Bao | 09e8493 | 2018-08-31 11:25:05 -0700 | [diff] [blame] | 652 | if (!LoadFileContents(source_filename, &source_file)) { |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 653 | LOG(ERROR) << "Failed to load source file"; |
| 654 | return false; |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 655 | } |
| 656 | |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 657 | uint8_t expected_sha1[SHA_DIGEST_LENGTH]; |
| 658 | if (ParseSha1(partition.hash, expected_sha1) != 0) { |
| 659 | LOG(ERROR) << "Failed to parse source hash \"" << partition.hash << "\""; |
| 660 | return false; |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 661 | } |
Yabin Cui | d483c20 | 2016-02-03 17:08:52 -0800 | [diff] [blame] | 662 | |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 663 | if (memcmp(source_file.sha1, expected_sha1, SHA_DIGEST_LENGTH) != 0) { |
| 664 | // The source doesn't have desired checksum. |
| 665 | LOG(ERROR) << "source \"" << source_filename << "\" doesn't have expected SHA-1 sum"; |
| 666 | LOG(ERROR) << "expected: " << partition.hash.substr(0, 8) |
| 667 | << ", found: " << short_sha1(source_file.sha1); |
| 668 | return false; |
Elliott Hughes | 63a3192 | 2016-06-09 17:41:22 -0700 | [diff] [blame] | 669 | } |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 670 | if (!WriteBufferToPartition(source_file, partition)) { |
| 671 | LOG(ERROR) << "Failed to write to " << partition; |
| 672 | return false; |
| 673 | } |
| 674 | return true; |
Yabin Cui | d483c20 | 2016-02-03 17:08:52 -0800 | [diff] [blame] | 675 | } |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 676 | |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 677 | static bool GenerateTarget(const Partition& target, const FileContents& source_file, |
| 678 | const Value& patch, const Value* bonus_data) { |
| 679 | uint8_t expected_sha1[SHA_DIGEST_LENGTH]; |
| 680 | if (ParseSha1(target.hash, expected_sha1) != 0) { |
| 681 | LOG(ERROR) << "Failed to parse target hash \"" << target.hash << "\""; |
| 682 | return false; |
| 683 | } |
| 684 | |
| 685 | if (patch.type != Value::Type::BLOB) { |
Tao Bao | 859bfc5 | 2018-04-25 23:00:27 -0700 | [diff] [blame] | 686 | LOG(ERROR) << "patch is not a blob"; |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 687 | return false; |
Yabin Cui | d483c20 | 2016-02-03 17:08:52 -0800 | [diff] [blame] | 688 | } |
| 689 | |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 690 | const char* header = patch.data.data(); |
| 691 | size_t header_bytes_read = patch.data.size(); |
Tao Bao | 6e02ea9 | 2016-11-17 11:24:07 -0800 | [diff] [blame] | 692 | bool use_bsdiff = false; |
| 693 | if (header_bytes_read >= 8 && memcmp(header, "BSDIFF40", 8) == 0) { |
| 694 | use_bsdiff = true; |
| 695 | } else if (header_bytes_read >= 8 && memcmp(header, "IMGDIFF2", 8) == 0) { |
| 696 | use_bsdiff = false; |
| 697 | } else { |
Tao Bao | 859bfc5 | 2018-04-25 23:00:27 -0700 | [diff] [blame] | 698 | LOG(ERROR) << "Unknown patch file format"; |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 699 | return false; |
Tao Bao | 6e02ea9 | 2016-11-17 11:24:07 -0800 | [diff] [blame] | 700 | } |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 701 | |
Tao Bao | 5ee2566 | 2018-07-11 15:55:32 -0700 | [diff] [blame] | 702 | // We write the original source to cache, in case the partition write is interrupted. |
| 703 | if (!CheckAndFreeSpaceOnCache(source_file.data.size())) { |
Tao Bao | 859bfc5 | 2018-04-25 23:00:27 -0700 | [diff] [blame] | 704 | LOG(ERROR) << "Not enough free space on /cache"; |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 705 | return false; |
Tao Bao | 40e144d | 2017-03-15 01:10:58 -0700 | [diff] [blame] | 706 | } |
Tao Bao | 09e8493 | 2018-08-31 11:25:05 -0700 | [diff] [blame] | 707 | if (!SaveFileContents(Paths::Get().cache_temp_source(), &source_file)) { |
Tao Bao | 859bfc5 | 2018-04-25 23:00:27 -0700 | [diff] [blame] | 708 | LOG(ERROR) << "Failed to back up source file"; |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 709 | return false; |
Tao Bao | 40e144d | 2017-03-15 01:10:58 -0700 | [diff] [blame] | 710 | } |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 711 | |
Tao Bao | 40e144d | 2017-03-15 01:10:58 -0700 | [diff] [blame] | 712 | // We store the decoded output in memory. |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 713 | FileContents patched; |
Tao Bao | 8b0b0f1 | 2018-04-19 21:02:13 -0700 | [diff] [blame] | 714 | SHA_CTX ctx; |
| 715 | SHA1_Init(&ctx); |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 716 | SinkFn sink = [&patched, &ctx](const unsigned char* data, size_t len) { |
Tao Bao | 8b0b0f1 | 2018-04-19 21:02:13 -0700 | [diff] [blame] | 717 | SHA1_Update(&ctx, data, len); |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 718 | patched.data.insert(patched.data.end(), data, data + len); |
Tao Bao | c0e1c46 | 2017-02-01 10:20:10 -0800 | [diff] [blame] | 719 | return len; |
| 720 | }; |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 721 | |
Tao Bao | 40e144d | 2017-03-15 01:10:58 -0700 | [diff] [blame] | 722 | int result; |
| 723 | if (use_bsdiff) { |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 724 | result = ApplyBSDiffPatch(source_file.data.data(), source_file.data.size(), patch, 0, sink); |
Tao Bao | 40e144d | 2017-03-15 01:10:58 -0700 | [diff] [blame] | 725 | } else { |
Tao Bao | 8b0b0f1 | 2018-04-19 21:02:13 -0700 | [diff] [blame] | 726 | result = |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 727 | ApplyImagePatch(source_file.data.data(), source_file.data.size(), patch, sink, bonus_data); |
Tao Bao | 40e144d | 2017-03-15 01:10:58 -0700 | [diff] [blame] | 728 | } |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 729 | |
Tao Bao | 40e144d | 2017-03-15 01:10:58 -0700 | [diff] [blame] | 730 | if (result != 0) { |
Tao Bao | 859bfc5 | 2018-04-25 23:00:27 -0700 | [diff] [blame] | 731 | LOG(ERROR) << "Failed to apply the patch: " << result; |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 732 | return false; |
Tao Bao | 40e144d | 2017-03-15 01:10:58 -0700 | [diff] [blame] | 733 | } |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 734 | |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 735 | SHA1_Final(patched.sha1, &ctx); |
| 736 | if (memcmp(patched.sha1, expected_sha1, SHA_DIGEST_LENGTH) != 0) { |
| 737 | LOG(ERROR) << "Patching did not produce the expected SHA-1 of " << short_sha1(expected_sha1); |
Tao Bao | 4f83430 | 2018-04-19 12:35:14 -0700 | [diff] [blame] | 738 | |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 739 | LOG(ERROR) << "target size " << patched.data.size() << " SHA-1 " << short_sha1(patched.sha1); |
Tao Bao | 859bfc5 | 2018-04-25 23:00:27 -0700 | [diff] [blame] | 740 | LOG(ERROR) << "source size " << source_file.data.size() << " SHA-1 " |
| 741 | << short_sha1(source_file.sha1); |
Tao Bao | 4f83430 | 2018-04-19 12:35:14 -0700 | [diff] [blame] | 742 | |
| 743 | uint8_t patch_digest[SHA_DIGEST_LENGTH]; |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 744 | SHA1(reinterpret_cast<const uint8_t*>(patch.data.data()), patch.data.size(), patch_digest); |
| 745 | LOG(ERROR) << "patch size " << patch.data.size() << " SHA-1 " << short_sha1(patch_digest); |
Tao Bao | 4f83430 | 2018-04-19 12:35:14 -0700 | [diff] [blame] | 746 | |
Tao Bao | 7ea515e | 2018-07-09 15:16:13 -0700 | [diff] [blame] | 747 | if (bonus_data != nullptr) { |
| 748 | uint8_t bonus_digest[SHA_DIGEST_LENGTH]; |
| 749 | SHA1(reinterpret_cast<const uint8_t*>(bonus_data->data.data()), bonus_data->data.size(), |
| 750 | bonus_digest); |
| 751 | LOG(ERROR) << "bonus size " << bonus_data->data.size() << " SHA-1 " |
| 752 | << short_sha1(bonus_digest); |
| 753 | } |
Tao Bao | 4f83430 | 2018-04-19 12:35:14 -0700 | [diff] [blame] | 754 | |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 755 | return false; |
Tao Bao | 6e02ea9 | 2016-11-17 11:24:07 -0800 | [diff] [blame] | 756 | } |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 757 | |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 758 | LOG(INFO) << " now " << short_sha1(expected_sha1); |
| 759 | |
Tao Bao | 40e144d | 2017-03-15 01:10:58 -0700 | [diff] [blame] | 760 | // Write back the temp file to the partition. |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 761 | if (!WriteBufferToPartition(patched, target)) { |
| 762 | LOG(ERROR) << "Failed to write patched data to " << target.name; |
| 763 | return false; |
Tao Bao | 6e02ea9 | 2016-11-17 11:24:07 -0800 | [diff] [blame] | 764 | } |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 765 | |
Tao Bao | 40e144d | 2017-03-15 01:10:58 -0700 | [diff] [blame] | 766 | // Delete the backup copy of the source. |
Tao Bao | 641fa97 | 2018-04-25 18:59:40 -0700 | [diff] [blame] | 767 | unlink(Paths::Get().cache_temp_source().c_str()); |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 768 | |
Tao Bao | 6e02ea9 | 2016-11-17 11:24:07 -0800 | [diff] [blame] | 769 | // Success! |
Tao Bao | 5609bc8 | 2018-06-20 00:30:48 -0700 | [diff] [blame] | 770 | return true; |
| 771 | } |
| 772 | |
| 773 | bool CheckPartition(const Partition& partition) { |
| 774 | FileContents target_file; |
| 775 | return ReadPartitionToBuffer(partition, &target_file, false); |
| 776 | } |
| 777 | |
| 778 | Partition Partition::Parse(const std::string& input_str, std::string* err) { |
| 779 | std::vector<std::string> pieces = android::base::Split(input_str, ":"); |
| 780 | if (pieces.size() != 4 || pieces[0] != "EMMC") { |
| 781 | *err = "Invalid number of tokens or non-eMMC target"; |
| 782 | return {}; |
| 783 | } |
| 784 | |
| 785 | size_t size; |
| 786 | if (!android::base::ParseUint(pieces[2], &size) || size == 0) { |
| 787 | *err = "Failed to parse \"" + pieces[2] + "\" as byte count"; |
| 788 | return {}; |
| 789 | } |
| 790 | |
| 791 | return Partition(pieces[1], size, pieces[3]); |
| 792 | } |
| 793 | |
| 794 | std::string Partition::ToString() const { |
| 795 | if (*this) { |
| 796 | return "EMMC:"s + name + ":" + std::to_string(size) + ":" + hash; |
| 797 | } |
| 798 | return "<invalid-partition>"; |
| 799 | } |
| 800 | |
| 801 | std::ostream& operator<<(std::ostream& os, const Partition& partition) { |
| 802 | os << partition.ToString(); |
| 803 | return os; |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 804 | } |