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 "ueventd.h"
17d9f0492fSopenharmony_ci#include <dirent.h>
18d9f0492fSopenharmony_ci#include <limits.h>
19d9f0492fSopenharmony_ci#include <fcntl.h>
20d9f0492fSopenharmony_ci#include <errno.h>
21d9f0492fSopenharmony_ci#include <stdlib.h>
22d9f0492fSopenharmony_ci#include <string.h>
23d9f0492fSopenharmony_ci#include <sys/stat.h>
24d9f0492fSopenharmony_ci#include <sys/sysmacros.h>
25d9f0492fSopenharmony_ci#include <fcntl.h>
26d9f0492fSopenharmony_ci#include <unistd.h>
27d9f0492fSopenharmony_ci
28d9f0492fSopenharmony_ci#include "ueventd_device_handler.h"
29d9f0492fSopenharmony_ci#include "ueventd_firmware_handler.h"
30d9f0492fSopenharmony_ci#include "ueventd_read_cfg.h"
31d9f0492fSopenharmony_ci#include "ueventd_socket.h"
32d9f0492fSopenharmony_ci#include "ueventd_utils.h"
33d9f0492fSopenharmony_ci#include "securec.h"
34d9f0492fSopenharmony_ci#define INIT_LOG_TAG "ueventd"
35d9f0492fSopenharmony_ci#include "init_log.h"
36d9f0492fSopenharmony_ci#include "init_utils.h"
37d9f0492fSopenharmony_ci
38d9f0492fSopenharmony_ci// buffer size refer to kernel kobject uevent
39d9f0492fSopenharmony_ci#define UEVENT_BUFFER_SIZE (2048 + 1)
40d9f0492fSopenharmony_cichar bootDevice[CMDLINE_VALUE_LEN_MAX] = { 0 };
41d9f0492fSopenharmony_ci#define WRITE_SIZE 4
42d9f0492fSopenharmony_ci
43d9f0492fSopenharmony_cistatic const char *actions[] = {
44d9f0492fSopenharmony_ci    [ACTION_ADD] = "add",
45d9f0492fSopenharmony_ci    [ACTION_REMOVE] = "remove",
46d9f0492fSopenharmony_ci    [ACTION_CHANGE] = "change",
47d9f0492fSopenharmony_ci    [ACTION_MOVE] = "move",
48d9f0492fSopenharmony_ci    [ACTION_ONLINE] = "online",
49d9f0492fSopenharmony_ci    [ACTION_OFFLINE] = "offline",
50d9f0492fSopenharmony_ci    [ACTION_BIND] = "bind",
51d9f0492fSopenharmony_ci    [ACTION_UNBIND] = "unbind",
52d9f0492fSopenharmony_ci    [ACTION_UNKNOWN] = "unknown",
53d9f0492fSopenharmony_ci};
54d9f0492fSopenharmony_ci
55d9f0492fSopenharmony_cistatic SUBSYSTEMTYPE GetSubsystemType(const char *subsystem)
56d9f0492fSopenharmony_ci{
57d9f0492fSopenharmony_ci    if (subsystem == NULL || *subsystem == '\0') {
58d9f0492fSopenharmony_ci        return SUBSYSTEM_EMPTY;
59d9f0492fSopenharmony_ci    }
60d9f0492fSopenharmony_ci
61d9f0492fSopenharmony_ci    if (strcmp(subsystem, "block") == 0) {
62d9f0492fSopenharmony_ci        return SUBSYSTEM_BLOCK;
63d9f0492fSopenharmony_ci    } else if (strcmp(subsystem, "platform") == 0) {
64d9f0492fSopenharmony_ci        return SUBSYSTEM_PLATFORM;
65d9f0492fSopenharmony_ci    } else if (strcmp(subsystem, "firmware") == 0) {
66d9f0492fSopenharmony_ci        return SUBSYSTEM_FIRMWARE;
67d9f0492fSopenharmony_ci    } else {
68d9f0492fSopenharmony_ci        return SUBSYSTEM_OTHERS;
69d9f0492fSopenharmony_ci    }
70d9f0492fSopenharmony_ci}
71d9f0492fSopenharmony_ci
72d9f0492fSopenharmony_ciconst char *ActionString(ACTION action)
73d9f0492fSopenharmony_ci{
74d9f0492fSopenharmony_ci    return actions[action];
75d9f0492fSopenharmony_ci}
76d9f0492fSopenharmony_ci
77d9f0492fSopenharmony_cistatic ACTION GetUeventAction(const char *action)
78d9f0492fSopenharmony_ci{
79d9f0492fSopenharmony_ci    if (action == NULL || *action == '\0') {
80d9f0492fSopenharmony_ci        return ACTION_UNKNOWN;
81d9f0492fSopenharmony_ci    }
82d9f0492fSopenharmony_ci
83d9f0492fSopenharmony_ci    if (STRINGEQUAL(action, "add")) {
84d9f0492fSopenharmony_ci        return ACTION_ADD;
85d9f0492fSopenharmony_ci    } else if (STRINGEQUAL(action, "remove")) {
86d9f0492fSopenharmony_ci        return ACTION_REMOVE;
87d9f0492fSopenharmony_ci    } else if (STRINGEQUAL(action, "change")) {
88d9f0492fSopenharmony_ci        return ACTION_CHANGE;
89d9f0492fSopenharmony_ci    } else if (STRINGEQUAL(action, "move")) {
90d9f0492fSopenharmony_ci        return ACTION_MOVE;
91d9f0492fSopenharmony_ci    } else if (STRINGEQUAL(action, "online")) {
92d9f0492fSopenharmony_ci        return ACTION_ONLINE;
93d9f0492fSopenharmony_ci    } else if (STRINGEQUAL(action, "offline")) {
94d9f0492fSopenharmony_ci        return ACTION_OFFLINE;
95d9f0492fSopenharmony_ci    } else if (STRINGEQUAL(action, "bind")) {
96d9f0492fSopenharmony_ci        return ACTION_BIND;
97d9f0492fSopenharmony_ci    } else if (STRINGEQUAL(action, "unbind")) {
98d9f0492fSopenharmony_ci        return ACTION_UNBIND;
99d9f0492fSopenharmony_ci    } else {
100d9f0492fSopenharmony_ci        return ACTION_UNKNOWN;
101d9f0492fSopenharmony_ci    }
102d9f0492fSopenharmony_ci}
103d9f0492fSopenharmony_ci
104d9f0492fSopenharmony_ciSTATIC void HandleUevent(const struct Uevent *uevent)
105d9f0492fSopenharmony_ci{
106d9f0492fSopenharmony_ci    if (uevent->action == ACTION_ADD || uevent->action == ACTION_CHANGE || uevent->action == ACTION_ONLINE) {
107d9f0492fSopenharmony_ci        ChangeSysAttributePermissions(uevent->syspath);
108d9f0492fSopenharmony_ci    }
109d9f0492fSopenharmony_ci
110d9f0492fSopenharmony_ci    SUBSYSTEMTYPE type = GetSubsystemType(uevent->subsystem);
111d9f0492fSopenharmony_ci    switch (type) {
112d9f0492fSopenharmony_ci        case SUBSYSTEM_BLOCK:
113d9f0492fSopenharmony_ci            HandleBlockDeviceEvent(uevent);
114d9f0492fSopenharmony_ci            break;
115d9f0492fSopenharmony_ci        case SUBSYSTEM_FIRMWARE:
116d9f0492fSopenharmony_ci            HandleFimwareDeviceEvent(uevent);
117d9f0492fSopenharmony_ci            break;
118d9f0492fSopenharmony_ci        case SUBSYSTEM_OTHERS:
119d9f0492fSopenharmony_ci            HandleOtherDeviceEvent(uevent);
120d9f0492fSopenharmony_ci            break;
121d9f0492fSopenharmony_ci        default:
122d9f0492fSopenharmony_ci            break;
123d9f0492fSopenharmony_ci    }
124d9f0492fSopenharmony_ci}
125d9f0492fSopenharmony_ci
126d9f0492fSopenharmony_ci#define DEFAULT_RW_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
127d9f0492fSopenharmony_ci
128d9f0492fSopenharmony_citypedef struct {
129d9f0492fSopenharmony_ci    const char *dev;
130d9f0492fSopenharmony_ci    mode_t mode;
131d9f0492fSopenharmony_ci} DYNAMIC_DEVICE_NODE;
132d9f0492fSopenharmony_ci
133d9f0492fSopenharmony_ci#define DEV_NODE_PATH_PREFIX "/dev/"
134d9f0492fSopenharmony_ci#define DEV_NODE_PATH_PREFIX_LEN 5
135d9f0492fSopenharmony_ci
136d9f0492fSopenharmony_cistatic const DYNAMIC_DEVICE_NODE DYNAMIC_DEVICES[] = {
137d9f0492fSopenharmony_ci    { DEV_NODE_PATH_PREFIX"tty",              S_IFCHR | DEFAULT_RW_MODE },
138d9f0492fSopenharmony_ci    { DEV_NODE_PATH_PREFIX"binder",           S_IFCHR | DEFAULT_RW_MODE },
139d9f0492fSopenharmony_ci    { DEV_NODE_PATH_PREFIX"console",          S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP },
140d9f0492fSopenharmony_ci    { DEV_NODE_PATH_PREFIX"mapper/control",          S_IFCHR | DEFAULT_RW_MODE }
141d9f0492fSopenharmony_ci};
142d9f0492fSopenharmony_ci
143d9f0492fSopenharmony_cistatic void HandleRequiredDynamicDeviceNodes(const struct Uevent *uevent)
144d9f0492fSopenharmony_ci{
145d9f0492fSopenharmony_ci    mode_t mask;
146d9f0492fSopenharmony_ci    size_t idx = 0;
147d9f0492fSopenharmony_ci
148d9f0492fSopenharmony_ci    if (uevent->deviceName == NULL) {
149d9f0492fSopenharmony_ci        return;
150d9f0492fSopenharmony_ci    }
151d9f0492fSopenharmony_ci
152d9f0492fSopenharmony_ci    while (idx < sizeof(DYNAMIC_DEVICES) / sizeof(DYNAMIC_DEVICES[0])) {
153d9f0492fSopenharmony_ci        if (strcmp(uevent->deviceName, DYNAMIC_DEVICES[idx].dev + DEV_NODE_PATH_PREFIX_LEN) != 0) {
154d9f0492fSopenharmony_ci            idx++;
155d9f0492fSopenharmony_ci            continue;
156d9f0492fSopenharmony_ci        }
157d9f0492fSopenharmony_ci
158d9f0492fSopenharmony_ci        if (strcmp(uevent->deviceName, "mapper/control") == 0) {
159d9f0492fSopenharmony_ci            HandleOtherDeviceEvent(uevent);
160d9f0492fSopenharmony_ci            return;
161d9f0492fSopenharmony_ci        }
162d9f0492fSopenharmony_ci
163d9f0492fSopenharmony_ci        // Matched
164d9f0492fSopenharmony_ci        mask = umask(0);
165d9f0492fSopenharmony_ci        if (mknod(DYNAMIC_DEVICES[idx].dev, DYNAMIC_DEVICES[idx].mode,
166d9f0492fSopenharmony_ci            makedev((unsigned int)uevent->major, (unsigned int)uevent->minor)) != 0) {
167d9f0492fSopenharmony_ci            INIT_LOGE("Create device node %s failed. %s", DYNAMIC_DEVICES[idx].dev, strerror(errno));
168d9f0492fSopenharmony_ci        }
169d9f0492fSopenharmony_ci        // Restore umask
170d9f0492fSopenharmony_ci        umask(mask);
171d9f0492fSopenharmony_ci        break;
172d9f0492fSopenharmony_ci    }
173d9f0492fSopenharmony_ci}
174d9f0492fSopenharmony_ci
175d9f0492fSopenharmony_cistatic void HandleRequiredBlockDeviceNodes(const struct Uevent *uevent, char **devices, int num)
176d9f0492fSopenharmony_ci{
177d9f0492fSopenharmony_ci    for (int i = 0; i < num; i++) {
178d9f0492fSopenharmony_ci        if (uevent->partitionName == NULL) {
179d9f0492fSopenharmony_ci            if (strstr(devices[i], uevent->deviceName) != NULL) {
180d9f0492fSopenharmony_ci                INIT_LOGI("%s match with required partition %s success, now handle it", devices[i], uevent->deviceName);
181d9f0492fSopenharmony_ci                HandleBlockDeviceEvent(uevent);
182d9f0492fSopenharmony_ci                return;
183d9f0492fSopenharmony_ci            }
184d9f0492fSopenharmony_ci        } else if (strstr(devices[i], uevent->partitionName) != NULL ||
185d9f0492fSopenharmony_ci            strstr(uevent->partitionName, "vendor") != NULL ||
186d9f0492fSopenharmony_ci            strstr(uevent->partitionName, "system") != NULL ||
187d9f0492fSopenharmony_ci            strstr(uevent->partitionName, "chipset") != NULL ||
188d9f0492fSopenharmony_ci            strstr(uevent->partitionName, "boot") != NULL ||
189d9f0492fSopenharmony_ci            strstr(uevent->partitionName, "ramdisk") != NULL ||
190d9f0492fSopenharmony_ci            strstr(uevent->partitionName, "rvt") != NULL ||
191d9f0492fSopenharmony_ci            strstr(uevent->partitionName, "dtbo") != NULL) {
192d9f0492fSopenharmony_ci            INIT_LOGI("Handle required partitionName %s", uevent->partitionName);
193d9f0492fSopenharmony_ci            HandleBlockDeviceEvent(uevent);
194d9f0492fSopenharmony_ci            return;
195d9f0492fSopenharmony_ci        }
196d9f0492fSopenharmony_ci    }
197d9f0492fSopenharmony_ci    INIT_LOGW("Not found device for partitionName %s ", uevent->partitionName);
198d9f0492fSopenharmony_ci}
199d9f0492fSopenharmony_ci
200d9f0492fSopenharmony_cistatic void HandleUeventRequired(const struct Uevent *uevent, char **devices, int num)
201d9f0492fSopenharmony_ci{
202d9f0492fSopenharmony_ci    INIT_ERROR_CHECK(devices != NULL && num > 0, return, "Fault parameters");
203d9f0492fSopenharmony_ci    if (uevent->action == ACTION_ADD) {
204d9f0492fSopenharmony_ci        ChangeSysAttributePermissions(uevent->syspath);
205d9f0492fSopenharmony_ci    }
206d9f0492fSopenharmony_ci    SUBSYSTEMTYPE type = GetSubsystemType(uevent->subsystem);
207d9f0492fSopenharmony_ci    if (type == SUBSYSTEM_BLOCK) {
208d9f0492fSopenharmony_ci        HandleRequiredBlockDeviceNodes(uevent, devices, num);
209d9f0492fSopenharmony_ci    } else if (type == SUBSYSTEM_OTHERS) {
210d9f0492fSopenharmony_ci        HandleRequiredDynamicDeviceNodes(uevent);
211d9f0492fSopenharmony_ci    } else {
212d9f0492fSopenharmony_ci        return;
213d9f0492fSopenharmony_ci    }
214d9f0492fSopenharmony_ci}
215d9f0492fSopenharmony_ci
216d9f0492fSopenharmony_cistatic void AddUevent(struct Uevent *uevent, const char *event, size_t len)
217d9f0492fSopenharmony_ci{
218d9f0492fSopenharmony_ci    if (STARTSWITH(event, "DEVPATH=")) {
219d9f0492fSopenharmony_ci        uevent->syspath = event + strlen("DEVPATH=");
220d9f0492fSopenharmony_ci    } else if (STARTSWITH(event, "SUBSYSTEM=")) {
221d9f0492fSopenharmony_ci        uevent->subsystem = event + strlen("SUBSYSTEM=");
222d9f0492fSopenharmony_ci    } else if (STARTSWITH(event, "ACTION=")) {
223d9f0492fSopenharmony_ci        uevent->action = GetUeventAction(event + strlen("ACTION="));
224d9f0492fSopenharmony_ci    } else if (STARTSWITH(event, "DEVNAME=")) {
225d9f0492fSopenharmony_ci        uevent->deviceName = event + strlen("DEVNAME=");
226d9f0492fSopenharmony_ci    } else if (STARTSWITH(event, "PARTNAME=")) {
227d9f0492fSopenharmony_ci        uevent->partitionName = event + strlen("PARTNAME=");
228d9f0492fSopenharmony_ci    } else if (STARTSWITH(event, "PARTN=")) {
229d9f0492fSopenharmony_ci        uevent->partitionNum = StringToInt(event + strlen("PARTN="), -1);
230d9f0492fSopenharmony_ci    } else if (STARTSWITH(event, "MAJOR=")) {
231d9f0492fSopenharmony_ci        uevent->major = StringToInt(event + strlen("MAJOR="), -1);
232d9f0492fSopenharmony_ci    } else if (STARTSWITH(event, "MINOR=")) {
233d9f0492fSopenharmony_ci        uevent->minor = StringToInt(event + strlen("MINOR="), -1);
234d9f0492fSopenharmony_ci    } else if (STARTSWITH(event, "DEVUID")) {
235d9f0492fSopenharmony_ci        uevent->ug.uid = (uid_t)StringToInt(event + strlen("DEVUID="), 0);
236d9f0492fSopenharmony_ci    } else if (STARTSWITH(event, "DEVGID")) {
237d9f0492fSopenharmony_ci        uevent->ug.gid = (gid_t)StringToInt(event + strlen("DEVGID="), 0);
238d9f0492fSopenharmony_ci    } else if (STARTSWITH(event, "FIRMWARE=")) {
239d9f0492fSopenharmony_ci        uevent->firmware = event + strlen("FIRMWARE=");
240d9f0492fSopenharmony_ci    } else if (STARTSWITH(event, "BUSNUM=")) {
241d9f0492fSopenharmony_ci        uevent->busNum = StringToInt(event + strlen("BUSNUM="), -1);
242d9f0492fSopenharmony_ci    } else if (STARTSWITH(event, "DEVNUM=")) {
243d9f0492fSopenharmony_ci        uevent->devNum = StringToInt(event + strlen("DEVNUM="), -1);
244d9f0492fSopenharmony_ci    }
245d9f0492fSopenharmony_ci
246d9f0492fSopenharmony_ci    // Ignore other events
247d9f0492fSopenharmony_ci    INIT_LOGV("got uevent message:\n"
248d9f0492fSopenharmony_ci              "subsystem: %s\n"
249d9f0492fSopenharmony_ci              "parition: %s:%d\n"
250d9f0492fSopenharmony_ci              "action: %s\n"
251d9f0492fSopenharmony_ci              "devpath: %s\n"
252d9f0492fSopenharmony_ci              "devname: %s\n"
253d9f0492fSopenharmony_ci              "devnode: %d:%d\n"
254d9f0492fSopenharmony_ci              "id: %d:%d",
255d9f0492fSopenharmony_ci              uevent->subsystem,
256d9f0492fSopenharmony_ci              uevent->partitionName, uevent->partitionNum,
257d9f0492fSopenharmony_ci              uevent->action,
258d9f0492fSopenharmony_ci              uevent->syspath,
259d9f0492fSopenharmony_ci              uevent->deviceName,
260d9f0492fSopenharmony_ci              uevent->major, uevent->minor,
261d9f0492fSopenharmony_ci              uevent->ug.uid, uevent->ug.gid);
262d9f0492fSopenharmony_ci}
263d9f0492fSopenharmony_ci
264d9f0492fSopenharmony_civoid ParseUeventMessage(const char *buffer, ssize_t length, struct Uevent *uevent)
265d9f0492fSopenharmony_ci{
266d9f0492fSopenharmony_ci    if (buffer == NULL || uevent == NULL || length == 0) {
267d9f0492fSopenharmony_ci        // Ignore invalid buffer
268d9f0492fSopenharmony_ci        return;
269d9f0492fSopenharmony_ci    }
270d9f0492fSopenharmony_ci
271d9f0492fSopenharmony_ci    // reset partition number, major and minor.
272d9f0492fSopenharmony_ci    uevent->partitionName = NULL;
273d9f0492fSopenharmony_ci    uevent->partitionNum = -1;
274d9f0492fSopenharmony_ci    uevent->major = -1;
275d9f0492fSopenharmony_ci    uevent->minor = -1;
276d9f0492fSopenharmony_ci    uevent->busNum = -1;
277d9f0492fSopenharmony_ci    uevent->devNum = -1;
278d9f0492fSopenharmony_ci    ssize_t pos = 0;
279d9f0492fSopenharmony_ci    while (pos < length) {
280d9f0492fSopenharmony_ci        const char *event = buffer + pos;
281d9f0492fSopenharmony_ci        size_t len = strlen(event);
282d9f0492fSopenharmony_ci        if (len == 0) {
283d9f0492fSopenharmony_ci            break;
284d9f0492fSopenharmony_ci        }
285d9f0492fSopenharmony_ci        AddUevent(uevent, event, len);
286d9f0492fSopenharmony_ci        pos += (ssize_t)len + 1;
287d9f0492fSopenharmony_ci    }
288d9f0492fSopenharmony_ci}
289d9f0492fSopenharmony_ci
290d9f0492fSopenharmony_civoid ProcessUevent(int sockFd, char **devices, int num)
291d9f0492fSopenharmony_ci{
292d9f0492fSopenharmony_ci    // One more bytes for '\0'
293d9f0492fSopenharmony_ci    char ueventBuffer[UEVENT_BUFFER_SIZE] = {};
294d9f0492fSopenharmony_ci    ssize_t n = 0;
295d9f0492fSopenharmony_ci    struct Uevent uevent = {};
296d9f0492fSopenharmony_ci    while ((n = ReadUeventMessage(sockFd, ueventBuffer, sizeof(ueventBuffer) - 1)) > 0) {
297d9f0492fSopenharmony_ci        ParseUeventMessage(ueventBuffer, n, &uevent);
298d9f0492fSopenharmony_ci        if (uevent.syspath == NULL) {
299d9f0492fSopenharmony_ci            INIT_LOGV("Ignore unexpected uevent");
300d9f0492fSopenharmony_ci            return;
301d9f0492fSopenharmony_ci        }
302d9f0492fSopenharmony_ci        if (devices != NULL && num > 0) {
303d9f0492fSopenharmony_ci            HandleUeventRequired(&uevent, devices, num);
304d9f0492fSopenharmony_ci        } else {
305d9f0492fSopenharmony_ci            HandleUevent(&uevent);
306d9f0492fSopenharmony_ci        }
307d9f0492fSopenharmony_ci    }
308d9f0492fSopenharmony_ci}
309d9f0492fSopenharmony_ci
310d9f0492fSopenharmony_cistatic void DoTrigger(const char *ueventPath, int sockFd, char **devices, int num)
311d9f0492fSopenharmony_ci{
312d9f0492fSopenharmony_ci    if (ueventPath == NULL || ueventPath[0] == '\0') {
313d9f0492fSopenharmony_ci        return;
314d9f0492fSopenharmony_ci    }
315d9f0492fSopenharmony_ci
316d9f0492fSopenharmony_ci    INIT_LOGV("------------------------\n"
317d9f0492fSopenharmony_ci              "\nTry to trigger \" %s \" now ...", ueventPath);
318d9f0492fSopenharmony_ci    int fd = open(ueventPath, O_WRONLY | O_CLOEXEC);
319d9f0492fSopenharmony_ci    if (fd < 0) {
320d9f0492fSopenharmony_ci        INIT_LOGE("Open \" %s \" failed, err = %d", ueventPath, errno);
321d9f0492fSopenharmony_ci        return;
322d9f0492fSopenharmony_ci    }
323d9f0492fSopenharmony_ci
324d9f0492fSopenharmony_ci    ssize_t n = write(fd, "add\n", WRITE_SIZE);
325d9f0492fSopenharmony_ci    close(fd);
326d9f0492fSopenharmony_ci    if (n < 0) {
327d9f0492fSopenharmony_ci        INIT_LOGE("Write \" %s \" failed, err = %d", ueventPath, errno);
328d9f0492fSopenharmony_ci        return;
329d9f0492fSopenharmony_ci    }
330d9f0492fSopenharmony_ci
331d9f0492fSopenharmony_ci    // uevent triggered, now handle it.
332d9f0492fSopenharmony_ci    if (sockFd >= 0) {
333d9f0492fSopenharmony_ci        ProcessUevent(sockFd, devices, num);
334d9f0492fSopenharmony_ci    }
335d9f0492fSopenharmony_ci}
336d9f0492fSopenharmony_ci
337d9f0492fSopenharmony_cistatic void Trigger(const char *path, int sockFd, char **devices, int num)
338d9f0492fSopenharmony_ci{
339d9f0492fSopenharmony_ci    if (path == NULL) {
340d9f0492fSopenharmony_ci        return;
341d9f0492fSopenharmony_ci    }
342d9f0492fSopenharmony_ci    DIR *dir = opendir(path);
343d9f0492fSopenharmony_ci    if (dir == NULL) {
344d9f0492fSopenharmony_ci        return;
345d9f0492fSopenharmony_ci    }
346d9f0492fSopenharmony_ci    struct dirent *dirent = NULL;
347d9f0492fSopenharmony_ci    while ((dirent = readdir(dir)) != NULL) {
348d9f0492fSopenharmony_ci        if (dirent->d_name[0] == '.') {
349d9f0492fSopenharmony_ci            continue;
350d9f0492fSopenharmony_ci        }
351d9f0492fSopenharmony_ci        if (dirent->d_type == DT_DIR) {
352d9f0492fSopenharmony_ci            char pathBuffer[PATH_MAX];
353d9f0492fSopenharmony_ci            if (snprintf_s(pathBuffer, PATH_MAX, PATH_MAX - 1, "%s/%s", path, dirent->d_name) == -1) {
354d9f0492fSopenharmony_ci                continue;
355d9f0492fSopenharmony_ci            }
356d9f0492fSopenharmony_ci            Trigger(pathBuffer, sockFd, devices, num);
357d9f0492fSopenharmony_ci        } else {
358d9f0492fSopenharmony_ci            if (strcmp(dirent->d_name, "uevent") != 0) {
359d9f0492fSopenharmony_ci                continue;
360d9f0492fSopenharmony_ci            }
361d9f0492fSopenharmony_ci            char ueventBuffer[PATH_MAX];
362d9f0492fSopenharmony_ci            if (snprintf_s(ueventBuffer, PATH_MAX, PATH_MAX - 1, "%s/%s", path, "uevent") == -1) {
363d9f0492fSopenharmony_ci                INIT_LOGW("Cannot build uevent path under %s", path);
364d9f0492fSopenharmony_ci                continue;
365d9f0492fSopenharmony_ci            }
366d9f0492fSopenharmony_ci            DoTrigger(ueventBuffer, sockFd, devices, num);
367d9f0492fSopenharmony_ci        }
368d9f0492fSopenharmony_ci    }
369d9f0492fSopenharmony_ci    closedir(dir);
370d9f0492fSopenharmony_ci}
371d9f0492fSopenharmony_ci
372d9f0492fSopenharmony_civoid RetriggerUeventByPath(int sockFd, char *path)
373d9f0492fSopenharmony_ci{
374d9f0492fSopenharmony_ci    Trigger(path, sockFd, NULL, 0);
375d9f0492fSopenharmony_ci}
376d9f0492fSopenharmony_ci
377d9f0492fSopenharmony_civoid RetriggerUevent(int sockFd, char **devices, int num)
378d9f0492fSopenharmony_ci{
379d9f0492fSopenharmony_ci    int ret = GetParameterFromCmdLine("default_boot_device", bootDevice, CMDLINE_VALUE_LEN_MAX);
380d9f0492fSopenharmony_ci    INIT_CHECK_ONLY_ELOG(ret == 0, "Failed get default_boot_device value from cmdline");
381d9f0492fSopenharmony_ci    Trigger("/sys/block", sockFd, devices, num);
382d9f0492fSopenharmony_ci    Trigger("/sys/class", sockFd, devices, num);
383d9f0492fSopenharmony_ci    Trigger("/sys/devices", sockFd, devices, num);
384d9f0492fSopenharmony_ci}
385