• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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