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