blob: 6b86c17a7a53d5bb0310bc491c3ae70864bed412 [file] [log] [blame]
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -08001/*
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 Baobd82b272016-01-21 13:49:03 -080017#include <errno.h>
18#include <fcntl.h>
19#include <inttypes.h>
20#include <stdio.h>
21#include <string.h>
22#include <sys/stat.h>
23#include <sys/types.h>
24#include <unistd.h>
25
Ken Sumrallf35d1ce2013-02-13 12:59:35 -080026#include <fs_mgr.h>
Tao Baobd82b272016-01-21 13:49:03 -080027
Yabin Cui6faf0262016-06-09 14:09:39 -070028#include <android-base/file.h>
Yabin Cuibf049bf2016-06-21 11:00:44 -070029#include <android-base/unique_fd.h>
Yabin Cui6faf0262016-06-09 14:09:39 -070030
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080031#include "bootloader.h"
32#include "common.h"
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080033#include "roots.h"
34
Yabin Cui6faf0262016-06-09 14:09:39 -070035static bool read_misc_partition(const Volume* v, size_t offset, size_t size, std::string* out);
36static bool write_misc_partition(const Volume* v, size_t offset, const std::string& in);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080037
Tao Baobd82b272016-01-21 13:49:03 -080038int get_bootloader_message(bootloader_message* out) {
Doug Zongkercc8cd3f2010-09-20 12:16:13 -070039 Volume* v = volume_for_path("/misc");
Tao Baobd82b272016-01-21 13:49:03 -080040 if (v == nullptr) {
41 LOGE("Cannot load volume /misc!\n");
42 return -1;
Adam Blissb2ceb692011-07-13 15:13:54 -070043 }
Elliott Hughes63a31922016-06-09 17:41:22 -070044 if (strcmp(v->fs_type, "emmc") == 0) {
Yabin Cui6faf0262016-06-09 14:09:39 -070045 std::string s;
46 if (!read_misc_partition(v, BOOTLOADER_MESSAGE_OFFSET_IN_MISC, sizeof(bootloader_message),
47 &s)) {
48 return -1;
49 }
50 memcpy(out, s.data(), s.size());
51 return 0;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080052 }
Yabin Cui6faf0262016-06-09 14:09:39 -070053 LOGE("Unknown misc partition fs_type \"%s\"\n", v->fs_type);
Doug Zongkercc8cd3f2010-09-20 12:16:13 -070054 return -1;
Doug Zongker04611da2010-08-12 15:35:29 -070055}
56
Yabin Cui6faf0262016-06-09 14:09:39 -070057bool read_wipe_package(size_t size, std::string* out) {
58 Volume* v = volume_for_path("/misc");
59 if (v == nullptr) {
60 LOGE("Cannot load volume /misc!\n");
61 return false;
62 }
63 if (strcmp(v->fs_type, "mtd") == 0) {
64 LOGE("Read wipe package on mtd is not supported.\n");
65 return false;
66 } else if (strcmp(v->fs_type, "emmc") == 0) {
67 return read_misc_partition(v, WIPE_PACKAGE_OFFSET_IN_MISC, size, out);
68 }
69 LOGE("Unknown misc partition fs_type \"%s\"\n", v->fs_type);
70 return false;
71}
72
Tao Baobd82b272016-01-21 13:49:03 -080073int set_bootloader_message(const bootloader_message* in) {
Doug Zongkercc8cd3f2010-09-20 12:16:13 -070074 Volume* v = volume_for_path("/misc");
Tao Baobd82b272016-01-21 13:49:03 -080075 if (v == nullptr) {
76 LOGE("Cannot load volume /misc!\n");
77 return -1;
Adam Blissb2ceb692011-07-13 15:13:54 -070078 }
Elliott Hughes63a31922016-06-09 17:41:22 -070079 if (strcmp(v->fs_type, "emmc") == 0) {
Yabin Cui6faf0262016-06-09 14:09:39 -070080 std::string s(reinterpret_cast<const char*>(in), sizeof(*in));
81 bool success = write_misc_partition(v, BOOTLOADER_MESSAGE_OFFSET_IN_MISC, s);
82 return success ? 0 : -1;
Doug Zongker04611da2010-08-12 15:35:29 -070083 }
Yabin Cui6faf0262016-06-09 14:09:39 -070084 LOGE("Unknown misc partition fs_type \"%s\"\n", v->fs_type);
Doug Zongkercc8cd3f2010-09-20 12:16:13 -070085 return -1;
Doug Zongker04611da2010-08-12 15:35:29 -070086}
87
Doug Zongkercc8cd3f2010-09-20 12:16:13 -070088// ------------------------------------
89// for misc partitions on block devices
90// ------------------------------------
91
Doug Zongkercfd256a2011-04-22 09:26:44 -070092static void wait_for_device(const char* fn) {
93 int tries = 0;
94 int ret;
Doug Zongkercfd256a2011-04-22 09:26:44 -070095 do {
96 ++tries;
Tao Baobd82b272016-01-21 13:49:03 -080097 struct stat buf;
Doug Zongkercfd256a2011-04-22 09:26:44 -070098 ret = stat(fn, &buf);
Tao Baobd82b272016-01-21 13:49:03 -080099 if (ret == -1) {
100 printf("failed to stat \"%s\" try %d: %s\n", fn, tries, strerror(errno));
Doug Zongkercfd256a2011-04-22 09:26:44 -0700101 sleep(1);
102 }
103 } while (ret && tries < 10);
Tao Baobd82b272016-01-21 13:49:03 -0800104
Doug Zongkercfd256a2011-04-22 09:26:44 -0700105 if (ret) {
Tao Baobd82b272016-01-21 13:49:03 -0800106 printf("failed to stat \"%s\"\n", fn);
Doug Zongkercfd256a2011-04-22 09:26:44 -0700107 }
108}
109
Yabin Cui6faf0262016-06-09 14:09:39 -0700110static bool read_misc_partition(const Volume* v, size_t offset, size_t size, std::string* out) {
Ken Sumrallf35d1ce2013-02-13 12:59:35 -0800111 wait_for_device(v->blk_device);
Yabin Cuibf049bf2016-06-21 11:00:44 -0700112 android::base::unique_fd fd(open(v->blk_device, O_RDONLY));
113 if (fd == -1) {
Yabin Cui6faf0262016-06-09 14:09:39 -0700114 LOGE("Failed to open \"%s\": %s\n", v->blk_device, strerror(errno));
115 return false;
Doug Zongkercc8cd3f2010-09-20 12:16:13 -0700116 }
Yabin Cuibf049bf2016-06-21 11:00:44 -0700117 if (lseek(fd, static_cast<off_t>(offset), SEEK_SET) != static_cast<off_t>(offset)) {
Yabin Cui6faf0262016-06-09 14:09:39 -0700118 LOGE("Failed to lseek \"%s\": %s\n", v->blk_device, strerror(errno));
119 return false;
Doug Zongkercc8cd3f2010-09-20 12:16:13 -0700120 }
Yabin Cui6faf0262016-06-09 14:09:39 -0700121 out->resize(size);
Yabin Cuibf049bf2016-06-21 11:00:44 -0700122 if (!android::base::ReadFully(fd, &(*out)[0], size)) {
Yabin Cui6faf0262016-06-09 14:09:39 -0700123 LOGE("Failed to read \"%s\": %s\n", v->blk_device, strerror(errno));
124 return false;
Doug Zongkercc8cd3f2010-09-20 12:16:13 -0700125 }
Yabin Cui6faf0262016-06-09 14:09:39 -0700126 return true;
Doug Zongkercc8cd3f2010-09-20 12:16:13 -0700127}
128
Yabin Cui6faf0262016-06-09 14:09:39 -0700129static bool write_misc_partition(const Volume* v, size_t offset, const std::string& in) {
Ken Sumrallf35d1ce2013-02-13 12:59:35 -0800130 wait_for_device(v->blk_device);
Elliott Hughesbcabd092016-03-22 20:19:22 -0700131 android::base::unique_fd fd(open(v->blk_device, O_WRONLY | O_SYNC));
132 if (fd == -1) {
Yabin Cui6faf0262016-06-09 14:09:39 -0700133 LOGE("Failed to open \"%s\": %s\n", v->blk_device, strerror(errno));
134 return false;
Doug Zongkercc8cd3f2010-09-20 12:16:13 -0700135 }
Yabin Cuibf049bf2016-06-21 11:00:44 -0700136 if (lseek(fd, static_cast<off_t>(offset), SEEK_SET) != static_cast<off_t>(offset)) {
Yabin Cui6faf0262016-06-09 14:09:39 -0700137 LOGE("Failed to lseek \"%s\": %s\n", v->blk_device, strerror(errno));
138 return false;
139 }
Yabin Cuibf049bf2016-06-21 11:00:44 -0700140 if (!android::base::WriteFully(fd, in.data(), in.size())) {
Yabin Cui6faf0262016-06-09 14:09:39 -0700141 LOGE("Failed to write \"%s\": %s\n", v->blk_device, strerror(errno));
142 return false;
Doug Zongkercc8cd3f2010-09-20 12:16:13 -0700143 }
Tao Baobd82b272016-01-21 13:49:03 -0800144
Elliott Hughesbcabd092016-03-22 20:19:22 -0700145 if (fsync(fd) == -1) {
Yabin Cui6faf0262016-06-09 14:09:39 -0700146 LOGE("Failed to fsync \"%s\": %s\n", v->blk_device, strerror(errno));
147 return false;
Doug Zongkercc8cd3f2010-09-20 12:16:13 -0700148 }
Yabin Cui6faf0262016-06-09 14:09:39 -0700149 return true;
Doug Zongkercc8cd3f2010-09-20 12:16:13 -0700150}