xref: /base/startup/init/ueventd/ueventd_main.c (revision d9f0492f)
1d9f0492fSopenharmony_ci/*
2d9f0492fSopenharmony_ci * Copyright (c) 2021 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
16d9f0492fSopenharmony_ci#include <limits.h>
17d9f0492fSopenharmony_ci#include <poll.h>
18d9f0492fSopenharmony_ci#include <unistd.h>
19d9f0492fSopenharmony_ci#include <stdbool.h>
20d9f0492fSopenharmony_ci#include "ueventd.h"
21d9f0492fSopenharmony_ci#include "ueventd_read_cfg.h"
22d9f0492fSopenharmony_ci#include "ueventd_socket.h"
23d9f0492fSopenharmony_ci#define INIT_LOG_TAG "ueventd"
24d9f0492fSopenharmony_ci#include "init_log.h"
25d9f0492fSopenharmony_ci#include "init_socket.h"
26d9f0492fSopenharmony_ci#include "parameter.h"
27d9f0492fSopenharmony_ci
28d9f0492fSopenharmony_cistatic bool IsComplete()
29d9f0492fSopenharmony_ci{
30d9f0492fSopenharmony_ci    static bool complete = false;
31d9f0492fSopenharmony_ci    if (complete) {
32d9f0492fSopenharmony_ci        return true;
33d9f0492fSopenharmony_ci    }
34d9f0492fSopenharmony_ci    char enable[8] = {0};
35d9f0492fSopenharmony_ci    int ret = GetParameter("bootevent.boot.completed", "", enable, sizeof(enable));
36d9f0492fSopenharmony_ci    if (ret != 0) {
37d9f0492fSopenharmony_ci        INIT_LOGE("Failed to get param value");
38d9f0492fSopenharmony_ci        return false;
39d9f0492fSopenharmony_ci    }
40d9f0492fSopenharmony_ci    if (strcmp(enable, "true") == 0) {
41d9f0492fSopenharmony_ci        INIT_LOGI("boot completed");
42d9f0492fSopenharmony_ci        complete = true;
43d9f0492fSopenharmony_ci        return true;
44d9f0492fSopenharmony_ci    }
45d9f0492fSopenharmony_ci    return false;
46d9f0492fSopenharmony_ci}
47d9f0492fSopenharmony_ci
48d9f0492fSopenharmony_cistatic void PollUeventdSocketTimeout(int ueventSockFd, bool ondemand)
49d9f0492fSopenharmony_ci{
50d9f0492fSopenharmony_ci    struct pollfd pfd = {};
51d9f0492fSopenharmony_ci    pfd.events = POLLIN;
52d9f0492fSopenharmony_ci    pfd.fd = ueventSockFd;
53d9f0492fSopenharmony_ci    int timeout = ondemand ? UEVENTD_POLL_TIME : -1;
54d9f0492fSopenharmony_ci    int ret = -1;
55d9f0492fSopenharmony_ci
56d9f0492fSopenharmony_ci    while (1) {
57d9f0492fSopenharmony_ci        pfd.revents = 0;
58d9f0492fSopenharmony_ci        ret = poll(&pfd, 1, timeout);
59d9f0492fSopenharmony_ci        if (ret == 0) {
60d9f0492fSopenharmony_ci            if (IsComplete()) {
61d9f0492fSopenharmony_ci                INIT_LOGI("poll ueventd socket timeout, ueventd exit");
62d9f0492fSopenharmony_ci                return;
63d9f0492fSopenharmony_ci            }
64d9f0492fSopenharmony_ci            INIT_LOGI("poll ueventd socket timeout, but init not complete");
65d9f0492fSopenharmony_ci        } else if (ret < 0) {
66d9f0492fSopenharmony_ci            INIT_LOGE("Failed to poll ueventd socket!");
67d9f0492fSopenharmony_ci            return;
68d9f0492fSopenharmony_ci        }
69d9f0492fSopenharmony_ci        if (pfd.revents & (POLLIN | POLLERR)) {
70d9f0492fSopenharmony_ci            ProcessUevent(ueventSockFd, NULL, 0); // Not require boot devices
71d9f0492fSopenharmony_ci        }
72d9f0492fSopenharmony_ci    }
73d9f0492fSopenharmony_ci}
74d9f0492fSopenharmony_ci
75d9f0492fSopenharmony_cistatic int UeventdRetrigger(void)
76d9f0492fSopenharmony_ci{
77d9f0492fSopenharmony_ci    const char *ueventdConfigs[] = {"/etc/ueventd.config", "/vendor/etc/ueventd.config", NULL};
78d9f0492fSopenharmony_ci    int i = 0;
79d9f0492fSopenharmony_ci    while (ueventdConfigs[i] != NULL) {
80d9f0492fSopenharmony_ci        ParseUeventdConfigFile(ueventdConfigs[i++]);
81d9f0492fSopenharmony_ci    }
82d9f0492fSopenharmony_ci    int ueventSockFd = UeventdSocketInit();
83d9f0492fSopenharmony_ci    if (ueventSockFd < 0) {
84d9f0492fSopenharmony_ci        INIT_LOGE("Failed to create uevent socket!");
85d9f0492fSopenharmony_ci        return -1;
86d9f0492fSopenharmony_ci    }
87d9f0492fSopenharmony_ci    RetriggerUevent(ueventSockFd, NULL, 0); // Not require boot devices
88d9f0492fSopenharmony_ci    return 0;
89d9f0492fSopenharmony_ci}
90d9f0492fSopenharmony_ci
91d9f0492fSopenharmony_cistatic int UeventdDaemon(int listen_only)
92d9f0492fSopenharmony_ci{
93d9f0492fSopenharmony_ci    // start log
94d9f0492fSopenharmony_ci    EnableInitLog(INIT_INFO);
95d9f0492fSopenharmony_ci    const char *ueventdConfigs[] = {"/etc/ueventd.config", "/vendor/etc/ueventd.config", NULL};
96d9f0492fSopenharmony_ci    int i = 0;
97d9f0492fSopenharmony_ci    while (ueventdConfigs[i] != NULL) {
98d9f0492fSopenharmony_ci        ParseUeventdConfigFile(ueventdConfigs[i++]);
99d9f0492fSopenharmony_ci    }
100d9f0492fSopenharmony_ci    bool ondemand = true;
101d9f0492fSopenharmony_ci    int ueventSockFd = GetControlSocket("ueventd");
102d9f0492fSopenharmony_ci    if (ueventSockFd < 0) {
103d9f0492fSopenharmony_ci        INIT_LOGW("Failed to get uevent socket, try to create");
104d9f0492fSopenharmony_ci        ueventSockFd = UeventdSocketInit();
105d9f0492fSopenharmony_ci        ondemand = false;
106d9f0492fSopenharmony_ci    }
107d9f0492fSopenharmony_ci    if (ueventSockFd < 0) {
108d9f0492fSopenharmony_ci        INIT_LOGE("Failed to create uevent socket!");
109d9f0492fSopenharmony_ci        return -1;
110d9f0492fSopenharmony_ci    }
111d9f0492fSopenharmony_ci    if (!listen_only && access(UEVENTD_FLAG, F_OK)) {
112d9f0492fSopenharmony_ci        INIT_LOGI("Ueventd started, trigger uevent");
113d9f0492fSopenharmony_ci        RetriggerUevent(ueventSockFd, NULL, 0); // Not require boot devices
114d9f0492fSopenharmony_ci        int fd = open(UEVENTD_FLAG, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
115d9f0492fSopenharmony_ci        if (fd < 0) {
116d9f0492fSopenharmony_ci            INIT_LOGE("Failed to create ueventd flag!");
117d9f0492fSopenharmony_ci            return -1;
118d9f0492fSopenharmony_ci        }
119d9f0492fSopenharmony_ci        (void)close(fd);
120d9f0492fSopenharmony_ci    } else {
121d9f0492fSopenharmony_ci        INIT_LOGI("ueventd start to process uevent message");
122d9f0492fSopenharmony_ci        ProcessUevent(ueventSockFd, NULL, 0); // Not require boot devices
123d9f0492fSopenharmony_ci    }
124d9f0492fSopenharmony_ci    PollUeventdSocketTimeout(ueventSockFd, ondemand);
125d9f0492fSopenharmony_ci    CloseUeventConfig();
126d9f0492fSopenharmony_ci    return 0;
127d9f0492fSopenharmony_ci}
128d9f0492fSopenharmony_ci
129d9f0492fSopenharmony_cistatic int UeventdEarlyBoot(void)
130d9f0492fSopenharmony_ci{
131d9f0492fSopenharmony_ci    int ueventSockFd = UeventdSocketInit();
132d9f0492fSopenharmony_ci    if (ueventSockFd < 0) {
133d9f0492fSopenharmony_ci        return -1;
134d9f0492fSopenharmony_ci    }
135d9f0492fSopenharmony_ci
136d9f0492fSopenharmony_ci    char *devices[] = {
137d9f0492fSopenharmony_ci        "/dev/block/vdb",
138d9f0492fSopenharmony_ci        "/dev/block/vdc"
139d9f0492fSopenharmony_ci    };
140d9f0492fSopenharmony_ci
141d9f0492fSopenharmony_ci    RetriggerUevent(ueventSockFd, devices, 2);
142d9f0492fSopenharmony_ci    close(ueventSockFd);
143d9f0492fSopenharmony_ci    return 0;
144d9f0492fSopenharmony_ci}
145d9f0492fSopenharmony_ci
146d9f0492fSopenharmony_ci#define UEVENTD_MODE_DEAMON     0
147d9f0492fSopenharmony_ci#define UEVENTD_MODE_EARLY_BOOT 1
148d9f0492fSopenharmony_ci#define UEVENTD_MODE_RETRIGGER  2
149d9f0492fSopenharmony_ci#define UEVENTD_MODE_LISTEN     3
150d9f0492fSopenharmony_ci
151d9f0492fSopenharmony_cistatic void usage(const char *name)
152d9f0492fSopenharmony_ci{
153d9f0492fSopenharmony_ci    if (name == NULL || strlen(name) > PROCESS_NAME_MAX_LENGTH) {
154d9f0492fSopenharmony_ci        return ;
155d9f0492fSopenharmony_ci    }
156d9f0492fSopenharmony_ci    printf("Usage: %s [OPTION]\n"
157d9f0492fSopenharmony_ci           "Listening kernel uevent to create device node.\n"
158d9f0492fSopenharmony_ci           "It will read configs from {/,/system,/chipset}/etc/ueventd.config.\n\n"
159d9f0492fSopenharmony_ci           "The options may be used to set listening mode.\n"
160d9f0492fSopenharmony_ci           "    -d, --daemon          working in deamon mode(default mode)\n"
161d9f0492fSopenharmony_ci           "    -b, --boot            working in early booting mode, create required device nodes\n"
162d9f0492fSopenharmony_ci           "    -l, --listen          listen in verbose mode\n"
163d9f0492fSopenharmony_ci           "    -r, --retrigger       retrigger all uevents\n"
164d9f0492fSopenharmony_ci           "    -v, --verbose         log level\n"
165d9f0492fSopenharmony_ci           "    -h, --help            print this help info\n", name);
166d9f0492fSopenharmony_ci}
167d9f0492fSopenharmony_ci
168d9f0492fSopenharmony_cistatic void UeventdLogPrint(int logLevel, uint32_t domain, const char *tag, const char *fmt, va_list vargs)
169d9f0492fSopenharmony_ci{
170d9f0492fSopenharmony_ci    if (logLevel < (int)GetInitLogLevel()) {
171d9f0492fSopenharmony_ci        return;
172d9f0492fSopenharmony_ci    }
173d9f0492fSopenharmony_ci    vprintf(fmt, vargs);
174d9f0492fSopenharmony_ci    printf("\n");
175d9f0492fSopenharmony_ci}
176d9f0492fSopenharmony_ci
177d9f0492fSopenharmony_ciint main(int argc, char *argv[])
178d9f0492fSopenharmony_ci{
179d9f0492fSopenharmony_ci    int opt;
180d9f0492fSopenharmony_ci    int daemon = UEVENTD_MODE_DEAMON;
181d9f0492fSopenharmony_ci
182d9f0492fSopenharmony_ci    while ((opt = getopt(argc, argv, "drblv:h")) != -1) {
183d9f0492fSopenharmony_ci        switch (opt) {
184d9f0492fSopenharmony_ci            case 'd':
185d9f0492fSopenharmony_ci                daemon = UEVENTD_MODE_DEAMON;
186d9f0492fSopenharmony_ci                break;
187d9f0492fSopenharmony_ci            case 'r':
188d9f0492fSopenharmony_ci                SetInitCommLog(UeventdLogPrint);
189d9f0492fSopenharmony_ci                daemon = UEVENTD_MODE_RETRIGGER;
190d9f0492fSopenharmony_ci                break;
191d9f0492fSopenharmony_ci            case 'b':
192d9f0492fSopenharmony_ci                SetInitCommLog(UeventdLogPrint);
193d9f0492fSopenharmony_ci                daemon = UEVENTD_MODE_EARLY_BOOT;
194d9f0492fSopenharmony_ci                break;
195d9f0492fSopenharmony_ci            case 'v':
196d9f0492fSopenharmony_ci                EnableInitLog(atoi(optarg));
197d9f0492fSopenharmony_ci                SetInitCommLog(UeventdLogPrint);
198d9f0492fSopenharmony_ci                break;
199d9f0492fSopenharmony_ci            case 'l':
200d9f0492fSopenharmony_ci                EnableInitLog(0);
201d9f0492fSopenharmony_ci                SetInitCommLog(UeventdLogPrint);
202d9f0492fSopenharmony_ci                daemon = UEVENTD_MODE_LISTEN;
203d9f0492fSopenharmony_ci                break;
204d9f0492fSopenharmony_ci            case 'h':
205d9f0492fSopenharmony_ci                usage(argv[0]);
206d9f0492fSopenharmony_ci                exit(0);
207d9f0492fSopenharmony_ci                break;
208d9f0492fSopenharmony_ci            default: /* '?' */
209d9f0492fSopenharmony_ci                fprintf(stderr, "Usage: %s [-t nsecs] [-n] name\n",
210d9f0492fSopenharmony_ci                        argv[0]);
211d9f0492fSopenharmony_ci                exit(EXIT_FAILURE);
212d9f0492fSopenharmony_ci        }
213d9f0492fSopenharmony_ci    }
214d9f0492fSopenharmony_ci
215d9f0492fSopenharmony_ci    if (daemon == UEVENTD_MODE_DEAMON) {
216d9f0492fSopenharmony_ci        return UeventdDaemon(0);
217d9f0492fSopenharmony_ci    } else if (daemon == UEVENTD_MODE_RETRIGGER) {
218d9f0492fSopenharmony_ci        return UeventdRetrigger();
219d9f0492fSopenharmony_ci    } else if (daemon == UEVENTD_MODE_LISTEN) {
220d9f0492fSopenharmony_ci        return UeventdDaemon(1);
221d9f0492fSopenharmony_ci    } else {
222d9f0492fSopenharmony_ci        UeventdEarlyBoot();
223d9f0492fSopenharmony_ci    }
224d9f0492fSopenharmony_ci
225d9f0492fSopenharmony_ci    return 0;
226d9f0492fSopenharmony_ci}
227