init_reboot.c 6.7 KB
Newer Older
Z
zhong_ning 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*
 * Copyright (c) 2020 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "init_reboot.h"

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mount.h>
#include <sys/prctl.h>
#include <sys/reboot.h>
S
sun_fan 已提交
26
#include "securec.h"
Z
zhong_ning 已提交
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
#include "init_service.h"
#include "init_service_manager.h"
#include "init_log.h"

#define MAX_VALUE_LENGTH 500
#define MAX_COMMAND_SIZE 20
#define MAX_UPDATE_SIZE 100

struct RBMiscUpdateMessage {
    char command[MAX_COMMAND_SIZE];
    char update[MAX_UPDATE_SIZE];
};

static bool RBMiscWriteUpdaterMessage(const char *path, struct RBMiscUpdateMessage *boot)
{
S
sun_fan 已提交
42 43 44 45
    if (path == NULL || boot == NULL) {
        INIT_LOGE("path or boot is NULL.");
        return false;
    }
Z
zhong_ning 已提交
46 47 48 49 50 51 52 53
    FILE* fp = fopen(path, "rb+");
    if (fp == NULL) {
        INIT_LOGE("open %s failed", path);
        return false;
    }

    size_t ret = fwrite(boot, sizeof(struct RBMiscUpdateMessage), 1, fp);
    if (ret < 0) {
Z
zhong_ning 已提交
54
        INIT_LOGE("write to misc failed");
Z
zhong_ning 已提交
55 56 57 58 59 60 61 62 63 64
        fclose(fp);
        return false;
    }

    fclose(fp);
    return true;
}

static bool RBMiscReadUpdaterMessage(const char *path, struct RBMiscUpdateMessage *boot)
{
S
sun_fan 已提交
65 66 67 68
    if (path == NULL || boot == NULL) {
        INIT_LOGE("path or boot is NULL.");
        return false;
    }
Z
zhong_ning 已提交
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
    FILE* fp = fopen(path, "rb");
    if (fp == NULL) {
        INIT_LOGE("open %s failed", path);
        return false;
    }

    size_t ret = fread(boot, 1, sizeof(struct RBMiscUpdateMessage), fp);
    if (ret <= 0) {
        INIT_LOGE("read to misc failed");
        fclose(fp);
        return false;
    }
    fclose(fp);
    return true;
}

static int GetMountStatusForMountPoint(const char *mountPoint)
{
S
sun_fan 已提交
87 88
    const int bufferMaxSize = 512;
    char buffer[bufferMaxSize];
Z
zhong_ning 已提交
89 90 91 92
    size_t n;
    const char *mountFile = "/proc/mounts";
    FILE *fp = fopen(mountFile, "r");
    if (fp == NULL) {
Z
zhong_ning 已提交
93
        INIT_LOGE("DoReboot %s can't open.", mountPoint);
Z
zhong_ning 已提交
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
        return 1;
    }

    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
        n = strlen(buffer);
        if (buffer[n - 1] == '\n') {
            buffer[n - 1] = '\0';
        }
        if (strstr(buffer, mountPoint) != NULL) {
            fclose(fp);
            return 1;
        }
    }

    // Cannot find it from system.
    fclose(fp);
    return 0;
}

void DoReboot(const char *value)
{
    if (value == NULL) {
Z
zhong_ning 已提交
116
        INIT_LOGE("DoReboot value = NULL");
Z
zhong_ning 已提交
117 118
        return;
    }
Z
zhong_ning 已提交
119
    INIT_LOGI("DoReboot value = %s", value);
Z
zhong_ning 已提交
120 121

    if (strlen(value) > MAX_VALUE_LENGTH) {
Z
zhong_ning 已提交
122
        INIT_LOGE("DoReboot reboot value error, value = %s.", value);
Z
zhong_ning 已提交
123 124 125
        return;
    }

S
sun_fan 已提交
126 127
    const char *valueData = NULL;
    if (strncmp(value, "reboot,", strlen("reboot,")) != 0) {
Z
zhong_ning 已提交
128
        INIT_LOGE("DoReboot reboot value = %s, must started with reboot ,error.", value);
S
sun_fan 已提交
129 130 131 132
        return;
    } else {
        valueData = value + strlen("reboot,");
    }
Z
fix bug  
zhong_ning 已提交
133 134 135 136
    if (strncmp(valueData, "shutdown", strlen("shutdown")) != 0
        && strncmp(valueData, "updater:", strlen("updater:")) != 0
        && strncmp(valueData, "updater", strlen("updater")) != 0
        && strncmp(valueData, "NoArgument", strlen("NoArgument")) != 0) {
Z
zhong_ning 已提交
137
        INIT_LOGE("DoReboot value = %s, parameters error.", value);
Z
fix bug  
zhong_ning 已提交
138 139
        return;
    }
S
sun_fan 已提交
140

Z
fix bug  
zhong_ning 已提交
141
    StopAllServicesBeforeReboot();
S
sun_fan 已提交
142
    if (GetMountStatusForMountPoint("/vendor") != 0) {
Z
zhong_ning 已提交
143
        if (umount("/vendor") != 0) {
Z
zhong_ning 已提交
144
            INIT_LOGE("DoReboot umount vendor failed! errno = %d.", errno);
Z
zhong_ning 已提交
145 146
        }
    }
S
sun_fan 已提交
147
    if (GetMountStatusForMountPoint("/data") != 0) {
Z
zhong_ning 已提交
148
        if (umount("/data") != 0) {
Z
zhong_ning 已提交
149
            INIT_LOGE("DoReboot umount data failed! errno = %d.", errno);
Z
zhong_ning 已提交
150 151 152
        }
    }
    // "shutdown"
S
sun_fan 已提交
153
    if (strncmp(valueData, "shutdown", strlen("shutdown")) == 0) {
Z
zhong_ning 已提交
154 155
        int ret = reboot(RB_POWER_OFF);
        if (ret != 0) {
Z
zhong_ning 已提交
156
            INIT_LOGE("DoReboot reboot(RB_POWER_OFF) failed! syscall ret %d, err %d.", ret, errno);
Z
zhong_ning 已提交
157 158 159 160 161 162 163 164
        }
        return;
    }
    // "updater" or "updater:"
    const char *miscFile = "/dev/block/platform/soc/10100000.himci.eMMC/by-name/misc";
    struct RBMiscUpdateMessage msg;
    bool ret = RBMiscReadUpdaterMessage(miscFile, &msg);
    if(!ret) {
Z
zhong_ning 已提交
165
        INIT_LOGE("DoReboot RBMiscReadUpdaterMessage error.");
Z
zhong_ning 已提交
166 167 168 169 170 171
        return;
    }
    const int commandSize = 12;
    snprintf(msg.command, MAX_COMMAND_SIZE, "%s", "boot_updater");
    msg.command[commandSize] = 0;

S
sun_fan 已提交
172 173
    if (strlen(valueData) > strlen("updater:") && strncmp(valueData, "updater:", strlen("updater:")) == 0) {
        const char *p = valueData + strlen("updater:");
S
sun_fan 已提交
174
        if (snprintf_s(msg.update, MAX_UPDATE_SIZE, MAX_UPDATE_SIZE - 1, "%s", p) == -1) {
Z
zhong_ning 已提交
175
            INIT_LOGE("DoReboot updater: RBMiscWriteUpdaterMessage error");
Z
zhong_ning 已提交
176 177 178 179 180
            return;
        }
        msg.update[MAX_UPDATE_SIZE - 1] = 0;
        ret = RBMiscWriteUpdaterMessage(miscFile, &msg);
        if(true != ret) {
Z
zhong_ning 已提交
181
            INIT_LOGE("DoReboot updater: RBMiscWriteUpdaterMessage error");
Z
zhong_ning 已提交
182 183 184 185
            return;
        }
        ret = reboot(RB_AUTOBOOT);
        if (ret != 0) {
Z
zhong_ning 已提交
186
            INIT_LOGE("DoReboot updater: reboot(RB_AUTOBOOT) failed! syscall ret %d, err %d.", ret, errno);
Z
zhong_ning 已提交
187 188 189
        }
        return;
    }
S
sun_fan 已提交
190
    if (strlen(valueData) == strlen("updater") && strncmp(valueData, "updater", strlen("updater")) == 0) {
Z
zhong_ning 已提交
191 192
        ret = RBMiscWriteUpdaterMessage(miscFile, &msg);
        if(true != ret) {
Z
zhong_ning 已提交
193
            INIT_LOGE("DoReboot updater RBMiscWriteUpdaterMessage error");
Z
zhong_ning 已提交
194 195 196 197
            return;
        }
        ret = reboot(RB_AUTOBOOT);
        if (ret != 0) {
Z
zhong_ning 已提交
198
            INIT_LOGE("DoReboot updater reboot(RB_AUTOBOOT) failed! syscall ret %d, err %d.", ret, errno);
Z
zhong_ning 已提交
199 200 201
        }
        return;
    }
S
sun_fan 已提交
202
    if (strlen(valueData) == strlen("NoArgument") && strncmp(valueData, "NoArgument", strlen("NoArgument")) == 0) {
Z
zhong_ning 已提交
203 204
        ret = reboot(RB_AUTOBOOT);
        if (ret != 0) {
Z
zhong_ning 已提交
205
            INIT_LOGE("DoReboot updater: reboot(RB_AUTOBOOT) failed! syscall ret %d, err %d.", ret, errno);
Z
zhong_ning 已提交
206 207 208
        }
        return;
    }
Z
zhong_ning 已提交
209
    INIT_LOGE("DoReboot value = %s, error.", value);
Z
zhong_ning 已提交
210 211 212 213
    return;

}