1 /*
2 * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved.
3 *
4 * UniProton is licensed under Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 * http://license.coscl.org.cn/MulanPSL2
8 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11 * See the Mulan PSL v2 for more details.
12 * Create: 2009-12-22
13 * Description: hook模块的初始化文件
14 */
15 #include "prt_idle.h"
16 #include "prt_cpu_external.h"
17 #include "prt_hook_internal.h"
18
19 OS_SEC_BSS union TagMhookCb g_hookCb[OS_HOOK_TYPE_TOTAL];
20
21 /*
22 * 有些模块在钩子变化时,希望得到及时通知。比如tick钩子需要做g_tickDispatcher置换等
23 */
24 OS_SEC_BSS OsHookChgFunc g_hookChgHandler[OS_HOOK_TYPE_TOTAL];
25 // 注册钩子用的锁
26 OS_SEC_BSS volatile uintptr_t g_hookRegLock;
27 OS_SEC_BSS MemAllocHook g_osMemAlloc;
28
29 /*
30 * 描述:内核钩子模块注册
31 */
OsHookRegister(struct HookModInfo * modInfo)32 OS_SEC_L4_TEXT U32 OsHookRegister(struct HookModInfo *modInfo)
33 {
34 U32 hookIndex;
35
36 for (hookIndex = 0; hookIndex < (U32)OS_HOOK_TYPE_NUM; hookIndex++) {
37 g_hookCb[hookIndex].num += modInfo->maxNum[hookIndex];
38 }
39
40 return OS_OK;
41 }
42
43 /*
44 * 描述:多钩子使用预留
45 */
OsMhookReserve(U32 hookType,U32 incCnt)46 OS_SEC_L4_TEXT void OsMhookReserve(U32 hookType, U32 incCnt)
47 {
48 g_hookCb[hookType].num += incCnt;
49 }
50
51 /*
52 * 描述:内核钩子模块初始化
53 */
OsHookConfigInit(void)54 OS_SEC_L4_TEXT U32 OsHookConfigInit(void)
55 {
56 U32 size = 0;
57 U32 hookCnt;
58 U32 hookIndex;
59 OsVoidFunc *hooks = NULL;
60
61 for (hookIndex = 0; hookIndex < OS_SHOOK_TYPE_START; hookIndex++) {
62 hookCnt = g_hookCb[hookIndex].num;
63 if (hookCnt > 0) {
64 // 增加一个用于保护节点
65 size += hookCnt + 1;
66 }
67 }
68
69 if (size == 0) { // 没有配置任何钩子
70 return OS_OK;
71 }
72
73 size = (U32)(size * sizeof(OsVoidFunc));
74
75 if (g_osMemAlloc != NULL) {
76 hooks = g_osMemAlloc(OS_MID_HOOK, OS_MEM_DEFAULT_FSC_PT, size);
77 }
78
79 if (hooks == NULL) {
80 return OS_ERRNO_HOOK_NO_MEMORY;
81 }
82
83 if (memset_s((void *)hooks, size, 0, size) != EOK) {
84 OS_GOTO_SYS_ERROR1();
85 }
86
87 for (hookIndex = 0; hookIndex < OS_SHOOK_TYPE_START; hookIndex++) {
88 hookCnt = g_hookCb[hookIndex].num;
89 if (hookCnt == 0) {
90 continue;
91 }
92
93 g_hookCb[hookIndex].mulHook = hooks;
94 *(hooks + hookCnt) = (OsVoidFunc)OS_MHOOK_BOUNDARY;
95 hooks += hookCnt + 1;
96 }
97
98 OS_SPIN_LOCK_INIT(g_hookRegLock);
99
100 return OS_OK;
101 }
102
103 /*
104 * 描述:多钩子添加
105 */
OsMhookAdd(U32 hookType,OsVoidFunc hook)106 OS_SEC_L4_TEXT U32 OsMhookAdd(U32 hookType, OsVoidFunc hook)
107 {
108 uintptr_t intSave;
109 OsVoidFunc *mHook = NULL;
110 U32 ret = OS_OK;
111 U32 hookCnt = 0;
112 OsVoidFunc *add = NULL;
113
114 mHook = g_hookCb[hookType].mulHook;
115
116 /* 配置多钩子数为0,返回错误码 */
117 if (mHook == NULL) {
118 return OS_ERRNO_HOOK_NOT_CFG;
119 }
120
121 HOOK_ADD_IRQ_LOCK(intSave);
122
123 while (OS_MHOOK_IS_VALID(*mHook)) {
124 /* 如果是之前删除过的Dead节点,直接跳过 */
125 if (*mHook == OS_MHOOK_NODE_DEAD) {
126 /* 记录第一个Dead节点,作为后面新添加节点 */
127 if (add == NULL) {
128 add = mHook;
129 }
130 mHook++;
131 continue;
132 }
133
134 /* 如果该钩子已经注册,返回错误码 */
135 if (*mHook == hook) {
136 HOOK_ADD_IRQ_UNLOCK(intSave);
137 return OS_ERRNO_HOOK_EXISTED;
138 }
139 mHook++;
140 hookCnt++;
141 }
142
143 /* 如果新添加节点没有从Dead节点上分配,从尾部划取一个节点 */
144 if (add == NULL) {
145 if (!OS_MHOOK_NOT_BOUNDARY(*mHook)) {
146 HOOK_ADD_IRQ_UNLOCK(intSave);
147 return OS_ERRNO_HOOK_FULL;
148 }
149 add = mHook;
150 }
151
152 /* 调用钩子变更通知钩子 */
153 if ((hookCnt == 0) && (g_hookChgHandler[hookType] != NULL)) {
154 ret = g_hookChgHandler[hookType](hookType, HOOK_ADD_FIRST);
155 }
156
157 /* 添加钩子 */
158 if (ret == OS_OK) {
159 *add = hook;
160 }
161
162 HOOK_ADD_IRQ_UNLOCK(intSave);
163 return ret;
164 }
165
166 /*
167 * 描述:多钩子删除
168 */
OsMhookDel(U32 hookType,OsVoidFunc hook)169 OS_SEC_L4_TEXT U32 OsMhookDel(U32 hookType, OsVoidFunc hook)
170 {
171 uintptr_t intSave;
172 OsVoidFunc *mHook = NULL;
173 U32 ret;
174 U32 hookCnt = 0;
175 OsVoidFunc *del = NULL;
176
177 mHook = g_hookCb[hookType].mulHook;
178 if (mHook == NULL) {
179 return OS_ERRNO_HOOK_NOT_CFG;
180 }
181
182 HOOK_DEL_IRQ_LOCK(intSave);
183
184 while (OS_MHOOK_IS_VALID(*mHook)) {
185 if (*mHook == OS_MHOOK_NODE_DEAD) {
186 mHook++;
187 continue;
188 }
189
190 if (*mHook == hook) {
191 // 可断言del为空
192 del = mHook;
193 }
194
195 mHook++;
196 hookCnt++;
197 }
198
199 if (del == NULL) {
200 HOOK_DEL_IRQ_UNLOCK(intSave);
201 return OS_ERRNO_HOOK_NOT_EXISTED;
202 }
203
204 if ((hookCnt == 1) && (g_hookChgHandler[hookType] != NULL)) {
205 ret = g_hookChgHandler[hookType](hookType, HOOK_DEL_LAST);
206 if (ret != OS_OK) {
207 HOOK_DEL_IRQ_UNLOCK(intSave);
208 return ret;
209 }
210 }
211
212 // 如果是最后一个,置为FREE,避免每次钩子调用遍历。 否则置为DEAD态。
213 if (OS_MHOOK_IS_VALID(*(del + 1))) {
214 *del = OS_MHOOK_NODE_DEAD;
215 } else {
216 *del-- = OS_HOOK_EMPTY;
217 while ((del >= g_hookCb[hookType].mulHook) && (*del == OS_MHOOK_NODE_DEAD)) {
218 *del-- = OS_HOOK_EMPTY;
219 }
220 }
221
222 HOOK_DEL_IRQ_UNLOCK(intSave);
223 return OS_OK;
224 }
225
226 /*
227 * 描述:钩子添加
228 */
OsHookAdd(enum HookType hookType,OsVoidFunc hook)229 OS_SEC_L4_TEXT U32 OsHookAdd(enum HookType hookType, OsVoidFunc hook)
230 {
231 if ((U32)hookType >= (U32)OS_HOOK_TYPE_NUM) {
232 return OS_ERRNO_HOOK_TYPE_INVALID;
233 }
234
235 if (hook == NULL) {
236 return OS_ERRNO_HOOK_PTR_NULL;
237 }
238
239 return OsMhookAdd((U32)hookType, hook);
240 }
241
242 /*
243 * 描述:钩子删除
244 */
OsHookDel(enum HookType hookType,OsVoidFunc hook)245 OS_SEC_L4_TEXT U32 OsHookDel(enum HookType hookType, OsVoidFunc hook)
246 {
247 if ((U32)hookType >= (U32)(OS_HOOK_TYPE_NUM)) {
248 return OS_ERRNO_HOOK_TYPE_INVALID;
249 }
250
251 if (hook == NULL) {
252 return OS_ERRNO_HOOK_PTR_NULL;
253 }
254
255 return OsMhookDel((U32)hookType, hook);
256 }
257
258 /*
259 * 描述:单钩子注册
260 */
OsShookReg(U32 hookType,OsVoidFunc hook)261 OS_SEC_L4_TEXT U32 OsShookReg(U32 hookType, OsVoidFunc hook)
262 {
263 uintptr_t intSave;
264 U32 ret = OS_OK;
265
266 if (!OS_IS_SHOOK_TYPE(hookType)) {
267 return OS_ERRNO_HOOK_TYPE_INVALID;
268 }
269
270 HOOK_ADD_IRQ_LOCK(intSave);
271
272 if (hook == NULL) { // unreg
273 if (g_hookCb[hookType].sigHook == NULL) {
274 HOOK_ADD_IRQ_UNLOCK(intSave);
275 return OS_OK;
276 }
277
278 if (g_hookChgHandler[hookType] != NULL) {
279 ret = g_hookChgHandler[hookType](hookType, HOOK_DEL_LAST);
280 }
281
282 if (ret == OS_OK) {
283 g_hookCb[hookType].sigHook = NULL;
284 }
285 } else {
286 if (g_hookCb[hookType].sigHook != NULL) {
287 HOOK_ADD_IRQ_UNLOCK(intSave);
288 return OS_ERRNO_HOOK_FULL;
289 }
290
291 if (g_hookChgHandler[hookType] != NULL) {
292 ret = g_hookChgHandler[hookType](hookType, HOOK_ADD_FIRST);
293 }
294
295 if (ret == OS_OK) {
296 g_hookCb[hookType].sigHook = hook;
297 }
298 }
299
300 HOOK_ADD_IRQ_UNLOCK(intSave);
301 return ret;
302 }
303
304 /*
305 * 描述:前置钩子添加
306 */
PRT_IdleAddPrefixHook(IdleHook hook)307 OS_SEC_L4_TEXT U32 PRT_IdleAddPrefixHook(IdleHook hook)
308 {
309 if (hook == NULL) {
310 return OS_ERRNO_SYS_PTR_NULL;
311 }
312
313 return OsShookReg(OS_HOOK_IDLE_PREFIX, (OsVoidFunc)hook);
314 }
315