• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }