1 /*
2 * Copyright (c) 2024-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <sys/mount.h>
17 #include <sys/stat.h>
18 #include <sys/wait.h>
19 #include "securec.h"
20 #include "init_utils.h"
21 #include "fs_dm.h"
22 #include "fs_manager/fs_manager.h"
23 #include "erofs_remount_overlay.h"
24
25 #define MODEM_DRIVER_MNT_PATH STARTUP_INIT_UT_PATH"/vendor/modem/modem_driver"
26 #define MODEM_VENDOR_MNT_PATH STARTUP_INIT_UT_PATH"/vendor/modem/modem_vendor"
27 #define MODEM_FW_MNT_PATH STARTUP_INIT_UT_PATH"/vendor/modem/modem_fw"
28 #define MODEM_DRIVER_EXCHANGE_PATH STARTUP_INIT_UT_PATH"/mnt/driver_exchange"
29 #define MODEM_VENDOR_EXCHANGE_PATH STARTUP_INIT_UT_PATH"/mnt/vendor_exchange"
30 #define MODEM_FW_EXCHANGE_PATH STARTUP_INIT_UT_PATH"/mnt/fw_exchange"
31 #define REMOUNT_RESULT_PATH STARTUP_INIT_UT_PATH"/data/service/el1/startup/remount/"
32 #define REMOUNT_RESULT_FLAG STARTUP_INIT_UT_PATH"/data/service/el1/startup/remount/remount.result.done"
33 #define DPA_MNT_PATH STARTUP_INIT_UT_PATH"/vendor/communication/dpa"
34 #define DPA_EXCHANGE_PATH STARTUP_INIT_UT_PATH"/mnt/dpa_exchange"
35
GetRemountResult(void)36 int GetRemountResult(void)
37 {
38 int fd = open(REMOUNT_RESULT_FLAG, O_RDONLY);
39 if (fd >= 0) {
40 char buff[1];
41 int ret = read(fd, buff, 1);
42 if (ret < 0) {
43 BEGET_LOGE("read remount.result.done failed errno %d", errno);
44 close(fd);
45 return REMOUNT_FAIL;
46 }
47 close(fd);
48 if (buff[0] == '0' + REMOUNT_SUCC) {
49 return REMOUNT_SUCC;
50 }
51 }
52 return REMOUNT_FAIL;
53 }
54
SetRemountResultFlag()55 void SetRemountResultFlag()
56 {
57 struct stat st;
58 int ret;
59
60 int statRet = stat(REMOUNT_RESULT_PATH, &st);
61 if (statRet != 0) {
62 ret = mkdir(REMOUNT_RESULT_PATH, MODE_MKDIR);
63 if (ret < 0 && errno != EEXIST) {
64 BEGET_LOGE("mkdir remount path failed errno %d", errno);
65 return;
66 }
67 }
68
69 int fd = open(REMOUNT_RESULT_FLAG, O_WRONLY | O_CREAT, 0644);
70 if (fd < 0) {
71 BEGET_LOGE("open remount.result.done failed errno %d", errno);
72 return;
73 }
74
75 char buff[1];
76 buff[0] = '0' + REMOUNT_SUCC;
77
78 ret = write(fd, buff, 1);
79 if (ret < 0) {
80 BEGET_LOGE("write buff failed errno %d", errno);
81 }
82 close(fd);
83 BEGET_LOGI("set remount result flag successfully");
84 }
85
Modem2Exchange(const char * modemPath,const char * exchangePath)86 INIT_STATIC int Modem2Exchange(const char *modemPath, const char *exchangePath)
87 {
88 int ret;
89 ret = mkdir(exchangePath, MODE_MKDIR);
90 if (ret) {
91 BEGET_LOGE("mkdir %s failed.", exchangePath);
92 } else {
93 BEGET_LOGI("mkdir %s succeed.", exchangePath);
94 }
95
96 ret = mount(modemPath, exchangePath, NULL, MS_BIND | MS_RDONLY, NULL);
97 if (ret) {
98 BEGET_LOGE("bind %s to %s failed.", modemPath, exchangePath);
99 } else {
100 BEGET_LOGI("bind %s to %s succeed.", modemPath, exchangePath);
101 }
102
103 return ret;
104 }
105
Exchange2Modem(const char * modemPath,const char * exchangePath)106 INIT_STATIC int Exchange2Modem(const char *modemPath, const char *exchangePath)
107 {
108 int ret;
109 struct stat statInfo;
110 if (lstat(exchangePath, &statInfo)) {
111 BEGET_LOGE("no exchangePath %s.", exchangePath);
112 return 0;
113 }
114
115 ret = mount(exchangePath, modemPath, NULL, MS_BIND | MS_RDONLY, NULL);
116 if (ret) {
117 BEGET_LOGE("bind %s to %s failed.", exchangePath, modemPath);
118 } else {
119 BEGET_LOGI("bind %s to %s succeed.", exchangePath, modemPath);
120 }
121
122 ret = umount(exchangePath);
123 if (ret) {
124 BEGET_LOGE("umount %s failed.", exchangePath);
125 } else {
126 BEGET_LOGI("umount %s succeed.", exchangePath);
127 }
128
129 ret = remove(exchangePath);
130 if (ret) {
131 BEGET_LOGE("remove %s failed.", exchangePath);
132 } else {
133 BEGET_LOGI("remove %s succeed.", exchangePath);
134 }
135
136 return ret;
137 }
138
OverlayRemountVendorPre(void)139 void OverlayRemountVendorPre(void)
140 {
141 struct stat statInfo;
142
143 if (!stat(MODEM_DRIVER_MNT_PATH, &statInfo)) {
144 Modem2Exchange(MODEM_DRIVER_MNT_PATH, MODEM_DRIVER_EXCHANGE_PATH);
145 }
146
147 if (!stat(MODEM_VENDOR_MNT_PATH, &statInfo)) {
148 Modem2Exchange(MODEM_VENDOR_MNT_PATH, MODEM_VENDOR_EXCHANGE_PATH);
149 }
150
151 if (!stat(MODEM_FW_MNT_PATH, &statInfo)) {
152 Modem2Exchange(MODEM_FW_MNT_PATH, MODEM_FW_EXCHANGE_PATH);
153 }
154
155 if (!stat(DPA_MNT_PATH, &statInfo)) {
156 Modem2Exchange(DPA_MNT_PATH, DPA_EXCHANGE_PATH);
157 }
158 }
159
OverlayRemountVendorPost()160 void OverlayRemountVendorPost()
161 {
162 Exchange2Modem(MODEM_DRIVER_MNT_PATH, MODEM_DRIVER_EXCHANGE_PATH);
163 Exchange2Modem(MODEM_VENDOR_MNT_PATH, MODEM_VENDOR_EXCHANGE_PATH);
164 Exchange2Modem(MODEM_FW_MNT_PATH, MODEM_FW_EXCHANGE_PATH);
165 Exchange2Modem(DPA_MNT_PATH, DPA_EXCHANGE_PATH);
166 }
167
MountOverlayOne(const char * mnt)168 int MountOverlayOne(const char *mnt)
169 {
170 if ((strcmp(mnt, MODEM_DRIVER_MNT_PATH) == 0) || (strcmp(mnt, MODEM_VENDOR_MNT_PATH) == 0)) {
171 return 0;
172 }
173 char dirLower[MAX_BUFFER_LEN] = {0};
174 char dirUpper[MAX_BUFFER_LEN] = {0};
175 char dirWork[MAX_BUFFER_LEN] = {0};
176 char mntOpt[MAX_BUFFER_LEN] = {0};
177
178 if (strcmp(mnt, "/usr") == 0) {
179 if (snprintf_s(dirLower, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "%s", "/system") < 0) {
180 BEGET_LOGE("copy system dirLower failed. errno %d", errno);
181 return -1;
182 }
183 } else {
184 if (snprintf_s(dirLower, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "%s%s", PREFIX_LOWER, mnt) < 0) {
185 BEGET_LOGE("copy dirLower failed. errno %d", errno);
186 return -1;
187 }
188 }
189
190 if (snprintf_s(dirUpper, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "%s%s%s", PREFIX_OVERLAY, mnt, PREFIX_UPPER) < 0) {
191 BEGET_LOGE("copy dirUpper failed. errno %d", errno);
192 return -1;
193 }
194
195 if (snprintf_s(dirWork, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "%s%s%s", PREFIX_OVERLAY, mnt, PREFIX_WORK) < 0) {
196 BEGET_LOGE("copy dirWork failed. errno %d", errno);
197 return -1;
198 }
199
200 if (snprintf_s(mntOpt, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1,
201 "upperdir=%s,lowerdir=%s,workdir=%s,override_creds=off", dirUpper, dirLower, dirWork) < 0) {
202 BEGET_LOGE("copy mntOpt failed. errno %d", errno);
203 return -1;
204 }
205
206 if (strcmp(mnt, "/usr") == 0) {
207 if (mount("overlay", "/system", "overlay", 0, mntOpt)) {
208 BEGET_LOGE("mount system overlay failed. errno %d", errno);
209 return -1;
210 }
211 } else {
212 if (mount("overlay", mnt, "overlay", 0, mntOpt)) {
213 BEGET_LOGE("mount overlay fs failed. errno %d", errno);
214 return -1;
215 }
216 }
217 BEGET_LOGI("mount overlay fs success on mnt:%s", mnt);
218 return 0;
219 }
220
RemountOverlay(void)221 int RemountOverlay(void)
222 {
223 char *remountPath[] = {
224 "/usr", "/vendor", "/sys_prod", "/chip_prod", "/preload", "/cust", "/version"
225 };
226 for (size_t i = 0; i < ARRAY_LENGTH(remountPath); i++) {
227 struct stat statInfo;
228 char dirMnt[MAX_BUFFER_LEN] = {0};
229 if (snprintf_s(dirMnt, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "/mnt/overlay%s/upper", remountPath[i]) < 0) {
230 BEGET_LOGE("copy dirMnt [%s] failed.", dirMnt);
231 return -1;
232 }
233
234 if (lstat(dirMnt, &statInfo)) {
235 BEGET_LOGW("dirMnt [%s] not exist.", dirMnt);
236 continue;
237 }
238
239 if (strcmp(remountPath[i], "/vendor") == 0) {
240 OverlayRemountVendorPre();
241 }
242
243 if (MountOverlayOne(remountPath[i])) {
244 BEGET_LOGE("mount overlay failed on mnt [%s].", dirMnt);
245 return -1;
246 }
247
248 if (strcmp(remountPath[i], "/vendor") == 0) {
249 OverlayRemountVendorPost();
250 }
251 }
252 return 0;
253 }