1d9f0492fSopenharmony_ci/*
2d9f0492fSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
3d9f0492fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4d9f0492fSopenharmony_ci * you may not use this file except in compliance with the License.
5d9f0492fSopenharmony_ci * You may obtain a copy of the License at
6d9f0492fSopenharmony_ci *
7d9f0492fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8d9f0492fSopenharmony_ci *
9d9f0492fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10d9f0492fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11d9f0492fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12d9f0492fSopenharmony_ci * See the License for the specific language governing permissions and
13d9f0492fSopenharmony_ci * limitations under the License.
14d9f0492fSopenharmony_ci */
15d9f0492fSopenharmony_ci#include <errno.h>
16d9f0492fSopenharmony_ci#include <limits.h>
17d9f0492fSopenharmony_ci#include <stdlib.h>
18d9f0492fSopenharmony_ci#include <sys/mount.h>
19d9f0492fSopenharmony_ci
20d9f0492fSopenharmony_ci#include "reboot_adp.h"
21d9f0492fSopenharmony_ci#include "fs_manager/fs_manager.h"
22d9f0492fSopenharmony_ci#include "init_utils.h"
23d9f0492fSopenharmony_ci#include "securec.h"
24d9f0492fSopenharmony_ci
25d9f0492fSopenharmony_ci#define MAX_COMMAND_SIZE 32
26d9f0492fSopenharmony_ci#define MAX_UPDATE_SIZE 1280
27d9f0492fSopenharmony_ci#define MAX_RESERVED_SIZE 736
28d9f0492fSopenharmony_ci
29d9f0492fSopenharmony_cistruct RBMiscUpdateMessage {
30d9f0492fSopenharmony_ci    char command[MAX_COMMAND_SIZE];
31d9f0492fSopenharmony_ci    char update[MAX_UPDATE_SIZE];
32d9f0492fSopenharmony_ci    char reserved[MAX_RESERVED_SIZE];
33d9f0492fSopenharmony_ci};
34d9f0492fSopenharmony_ci
35d9f0492fSopenharmony_cistatic int RBMiscWriteUpdaterMessage(const char *path, const struct RBMiscUpdateMessage *boot)
36d9f0492fSopenharmony_ci{
37d9f0492fSopenharmony_ci    char *realPath = GetRealPath(path);
38d9f0492fSopenharmony_ci    BEGET_CHECK_RETURN_VALUE(realPath != NULL, -1);
39d9f0492fSopenharmony_ci    int ret = -1;
40d9f0492fSopenharmony_ci    FILE *fp = fopen(realPath, "rb+");
41d9f0492fSopenharmony_ci    free(realPath);
42d9f0492fSopenharmony_ci    realPath = NULL;
43d9f0492fSopenharmony_ci    if (fp != NULL) {
44d9f0492fSopenharmony_ci        size_t writeLen = fwrite(boot, sizeof(struct RBMiscUpdateMessage), 1, fp);
45d9f0492fSopenharmony_ci        BEGET_ERROR_CHECK(writeLen == 1, ret = -1, "Failed to write misc for reboot");
46d9f0492fSopenharmony_ci        (void)fclose(fp);
47d9f0492fSopenharmony_ci        ret = 0;
48d9f0492fSopenharmony_ci    }
49d9f0492fSopenharmony_ci    return ret;
50d9f0492fSopenharmony_ci}
51d9f0492fSopenharmony_ci
52d9f0492fSopenharmony_cistatic int RBMiscReadUpdaterMessage(const char *path, struct RBMiscUpdateMessage *boot)
53d9f0492fSopenharmony_ci{
54d9f0492fSopenharmony_ci    int ret = -1;
55d9f0492fSopenharmony_ci    FILE *fp = NULL;
56d9f0492fSopenharmony_ci    char *realPath = GetRealPath(path);
57d9f0492fSopenharmony_ci    if (realPath != NULL) {
58d9f0492fSopenharmony_ci        fp = fopen(realPath, "rb");
59d9f0492fSopenharmony_ci        free(realPath);
60d9f0492fSopenharmony_ci        realPath = NULL;
61d9f0492fSopenharmony_ci    } else {
62d9f0492fSopenharmony_ci        fp = fopen(path, "rb");
63d9f0492fSopenharmony_ci    }
64d9f0492fSopenharmony_ci    if (fp != NULL) {
65d9f0492fSopenharmony_ci        size_t readLen = fread(boot, 1, sizeof(struct RBMiscUpdateMessage), fp);
66d9f0492fSopenharmony_ci        (void)fclose(fp);
67d9f0492fSopenharmony_ci        BEGET_ERROR_CHECK(readLen > 0, ret = -1, "Failed to read misc for reboot");
68d9f0492fSopenharmony_ci        ret = 0;
69d9f0492fSopenharmony_ci    }
70d9f0492fSopenharmony_ci    return ret;
71d9f0492fSopenharmony_ci}
72d9f0492fSopenharmony_ci
73d9f0492fSopenharmony_ciint GetRebootReasonFromMisc(char *reason, size_t size)
74d9f0492fSopenharmony_ci{
75d9f0492fSopenharmony_ci    char miscFile[PATH_MAX] = {0};
76d9f0492fSopenharmony_ci    int ret = GetBlockDevicePath("/misc", miscFile, PATH_MAX);
77d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(ret == 0, return -1, "Failed to get misc path");
78d9f0492fSopenharmony_ci    struct RBMiscUpdateMessage msg;
79d9f0492fSopenharmony_ci    ret = RBMiscReadUpdaterMessage(miscFile, &msg);
80d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(ret == 0, return -1, "Failed to get misc info");
81d9f0492fSopenharmony_ci    return strcpy_s(reason, size, msg.command);
82d9f0492fSopenharmony_ci}
83d9f0492fSopenharmony_ci
84d9f0492fSopenharmony_ciint UpdateMiscMessage(const char *valueData, const char *cmd, const char *cmdExt, const char *boot)
85d9f0492fSopenharmony_ci{
86d9f0492fSopenharmony_ci    char miscFile[PATH_MAX] = {0};
87d9f0492fSopenharmony_ci    int ret = GetBlockDevicePath("/misc", miscFile, PATH_MAX);
88d9f0492fSopenharmony_ci    // no misc do not updater, so return ok
89d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(ret == 0, return 0, "Failed to get misc path for %s.", valueData);
90d9f0492fSopenharmony_ci
91d9f0492fSopenharmony_ci    // "updater" or "updater:"
92d9f0492fSopenharmony_ci    struct RBMiscUpdateMessage msg;
93d9f0492fSopenharmony_ci    ret = RBMiscReadUpdaterMessage(miscFile, &msg);
94d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(ret == 0, return -1, "Failed to get misc info for %s.", cmd);
95d9f0492fSopenharmony_ci
96d9f0492fSopenharmony_ci    if (boot != NULL) {
97d9f0492fSopenharmony_ci        ret = snprintf_s(msg.command, MAX_COMMAND_SIZE, MAX_COMMAND_SIZE - 1, "%s", boot);
98d9f0492fSopenharmony_ci        BEGET_ERROR_CHECK(ret > 0, return -1, "Failed to format cmd for %s.", cmd);
99d9f0492fSopenharmony_ci        msg.command[MAX_COMMAND_SIZE - 1] = 0;
100d9f0492fSopenharmony_ci    } else {
101d9f0492fSopenharmony_ci        ret = memset_s(msg.command, MAX_COMMAND_SIZE, 0, MAX_COMMAND_SIZE);
102d9f0492fSopenharmony_ci        BEGET_ERROR_CHECK(ret == 0, return -1, "Failed to format cmd for %s.", cmd);
103d9f0492fSopenharmony_ci    }
104d9f0492fSopenharmony_ci
105d9f0492fSopenharmony_ci    if (strncmp(cmd, "updater", strlen("updater")) != 0) {
106d9f0492fSopenharmony_ci        if ((cmdExt != NULL) && (valueData != NULL) && (strncmp(valueData, cmdExt, strlen(cmdExt)) == 0)) {
107d9f0492fSopenharmony_ci            const char *p = valueData + strlen(cmdExt);
108d9f0492fSopenharmony_ci            ret = snprintf_s(msg.update, MAX_UPDATE_SIZE, MAX_UPDATE_SIZE - 1, "%s", p);
109d9f0492fSopenharmony_ci            BEGET_ERROR_CHECK(ret > 0, return -1, "Failed to format param for %s.", cmd);
110d9f0492fSopenharmony_ci            msg.update[MAX_UPDATE_SIZE - 1] = 0;
111d9f0492fSopenharmony_ci        } else {
112d9f0492fSopenharmony_ci            ret = memset_s(msg.update, MAX_UPDATE_SIZE, 0, MAX_UPDATE_SIZE);
113d9f0492fSopenharmony_ci            BEGET_ERROR_CHECK(ret == 0, return -1, "Failed to format update for %s.", cmd);
114d9f0492fSopenharmony_ci        }
115d9f0492fSopenharmony_ci    }
116d9f0492fSopenharmony_ci
117d9f0492fSopenharmony_ci    if (RBMiscWriteUpdaterMessage(miscFile, &msg) == 0) {
118d9f0492fSopenharmony_ci        return 0;
119d9f0492fSopenharmony_ci    }
120d9f0492fSopenharmony_ci    return -1;
121d9f0492fSopenharmony_ci}
122