1 /*
2 * Copyright (c) 2022 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 #include <errno.h>
16 #include <limits.h>
17 #include <stdlib.h>
18 #include <sys/mount.h>
19
20 #include "reboot_adp.h"
21 #include "fs_manager/fs_manager.h"
22 #include "init_utils.h"
23 #include "securec.h"
24
25 #define MAX_COMMAND_SIZE 32
26 #define MAX_UPDATE_SIZE 1280
27 #define MAX_RESERVED_SIZE 736
28
29 struct RBMiscUpdateMessage {
30 char command[MAX_COMMAND_SIZE];
31 char update[MAX_UPDATE_SIZE];
32 char reserved[MAX_RESERVED_SIZE];
33 };
34
RBMiscWriteUpdaterMessage(const char * path,const struct RBMiscUpdateMessage * boot)35 static int RBMiscWriteUpdaterMessage(const char *path, const struct RBMiscUpdateMessage *boot)
36 {
37 char *realPath = GetRealPath(path);
38 BEGET_CHECK_RETURN_VALUE(realPath != NULL, -1);
39 int ret = -1;
40 FILE *fp = fopen(realPath, "rb+");
41 free(realPath);
42 realPath = NULL;
43 if (fp != NULL) {
44 size_t writeLen = fwrite(boot, sizeof(struct RBMiscUpdateMessage), 1, fp);
45 BEGET_ERROR_CHECK(writeLen == 1, ret = -1, "Failed to write misc for reboot");
46 (void)fclose(fp);
47 ret = 0;
48 }
49 return ret;
50 }
51
RBMiscReadUpdaterMessage(const char * path,struct RBMiscUpdateMessage * boot)52 static int RBMiscReadUpdaterMessage(const char *path, struct RBMiscUpdateMessage *boot)
53 {
54 int ret = -1;
55 FILE *fp = NULL;
56 char *realPath = GetRealPath(path);
57 if (realPath != NULL) {
58 fp = fopen(realPath, "rb");
59 free(realPath);
60 realPath = NULL;
61 } else {
62 fp = fopen(path, "rb");
63 }
64 if (fp != NULL) {
65 size_t readLen = fread(boot, 1, sizeof(struct RBMiscUpdateMessage), fp);
66 (void)fclose(fp);
67 BEGET_ERROR_CHECK(readLen > 0, ret = -1, "Failed to read misc for reboot");
68 ret = 0;
69 }
70 return ret;
71 }
72
GetRebootReasonFromMisc(char * reason,size_t size)73 int GetRebootReasonFromMisc(char *reason, size_t size)
74 {
75 char miscFile[PATH_MAX] = {0};
76 int ret = GetBlockDevicePath("/misc", miscFile, PATH_MAX);
77 BEGET_ERROR_CHECK(ret == 0, return -1, "Failed to get misc path");
78 struct RBMiscUpdateMessage msg;
79 ret = RBMiscReadUpdaterMessage(miscFile, &msg);
80 BEGET_ERROR_CHECK(ret == 0, return -1, "Failed to get misc info");
81 return strcpy_s(reason, size, msg.command);
82 }
83
UpdateMiscMessage(const char * valueData,const char * cmd,const char * cmdExt,const char * boot)84 int UpdateMiscMessage(const char *valueData, const char *cmd, const char *cmdExt, const char *boot)
85 {
86 char miscFile[PATH_MAX] = {0};
87 int ret = GetBlockDevicePath("/misc", miscFile, PATH_MAX);
88 // no misc do not updater, so return ok
89 BEGET_ERROR_CHECK(ret == 0, return 0, "Failed to get misc path for %s.", valueData);
90
91 // "updater" or "updater:"
92 struct RBMiscUpdateMessage msg;
93 ret = RBMiscReadUpdaterMessage(miscFile, &msg);
94 BEGET_ERROR_CHECK(ret == 0, return -1, "Failed to get misc info for %s.", cmd);
95
96 if (boot != NULL) {
97 ret = snprintf_s(msg.command, MAX_COMMAND_SIZE, MAX_COMMAND_SIZE - 1, "%s", boot);
98 BEGET_ERROR_CHECK(ret > 0, return -1, "Failed to format cmd for %s.", cmd);
99 msg.command[MAX_COMMAND_SIZE - 1] = 0;
100 } else {
101 ret = memset_s(msg.command, MAX_COMMAND_SIZE, 0, MAX_COMMAND_SIZE);
102 BEGET_ERROR_CHECK(ret == 0, return -1, "Failed to format cmd for %s.", cmd);
103 }
104
105 if (strncmp(cmd, "updater", strlen("updater")) != 0) {
106 if ((cmdExt != NULL) && (valueData != NULL) && (strncmp(valueData, cmdExt, strlen(cmdExt)) == 0)) {
107 const char *p = valueData + strlen(cmdExt);
108 ret = snprintf_s(msg.update, MAX_UPDATE_SIZE, MAX_UPDATE_SIZE - 1, "%s", p);
109 BEGET_ERROR_CHECK(ret > 0, return -1, "Failed to format param for %s.", cmd);
110 msg.update[MAX_UPDATE_SIZE - 1] = 0;
111 } else {
112 ret = memset_s(msg.update, MAX_UPDATE_SIZE, 0, MAX_UPDATE_SIZE);
113 BEGET_ERROR_CHECK(ret == 0, return -1, "Failed to format update for %s.", cmd);
114 }
115 }
116
117 if (RBMiscWriteUpdaterMessage(miscFile, &msg) == 0) {
118 return 0;
119 }
120 return -1;
121 }
122