• 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     return OS_OK;
99 }
100 
101 /*
102  * 描述:多钩子添加
103  */
OsMhookAdd(U32 hookType,OsVoidFunc hook)104 OS_SEC_L4_TEXT U32 OsMhookAdd(U32 hookType, OsVoidFunc hook)
105 {
106     uintptr_t intSave;
107     OsVoidFunc *mHook = NULL;
108     U32 ret = OS_OK;
109     U32 hookCnt = 0;
110     OsVoidFunc *add = NULL;
111 
112     mHook = g_hookCb[hookType].mulHook;
113 
114     /* 配置多钩子数为0,返回错误码 */
115     if (mHook == NULL) {
116         return OS_ERRNO_HOOK_NOT_CFG;
117     }
118 
119     HOOK_ADD_IRQ_LOCK(intSave);
120 
121     while (OS_MHOOK_IS_VALID(*mHook)) {
122         /* 如果是之前删除过的Dead节点,直接跳过 */
123         if (*mHook == OS_MHOOK_NODE_DEAD) {
124             /* 记录第一个Dead节点,作为后面新添加节点 */
125             if (add == NULL) {
126                 add = mHook;
127             }
128             mHook++;
129             continue;
130         }
131 
132         /* 如果该钩子已经注册,返回错误码 */
133         if (*mHook == hook) {
134             HOOK_ADD_IRQ_UNLOCK(intSave);
135             return OS_ERRNO_HOOK_EXISTED;
136         }
137         mHook++;
138         hookCnt++;
139     }
140 
141     /* 如果新添加节点没有从Dead节点上分配,从尾部划取一个节点 */
142     if (add == NULL) {
143         if (!OS_MHOOK_NOT_BOUNDARY(*mHook)) {
144             HOOK_ADD_IRQ_UNLOCK(intSave);
145             return OS_ERRNO_HOOK_FULL;
146         }
147         add = mHook;
148     }
149 
150     /* 调用钩子变更通知钩子 */
151     if ((hookCnt == 0) && (g_hookChgHandler[hookType] != NULL)) {
152         ret = g_hookChgHandler[hookType](hookType, HOOK_ADD_FIRST);
153     }
154 
155     /* 添加钩子 */
156     if (ret == OS_OK) {
157         *add = hook;
158     }
159 
160     HOOK_ADD_IRQ_UNLOCK(intSave);
161     return ret;
162 }
163 
164 /*
165  * 描述:多钩子删除
166  */
OsMhookDel(U32 hookType,OsVoidFunc hook)167 OS_SEC_L4_TEXT U32 OsMhookDel(U32 hookType, OsVoidFunc hook)
168 {
169     uintptr_t intSave;
170     OsVoidFunc *mHook = NULL;
171     U32 ret;
172     U32 hookCnt = 0;
173     OsVoidFunc *del = NULL;
174 
175     mHook = g_hookCb[hookType].mulHook;
176     if (mHook == NULL) {
177         return OS_ERRNO_HOOK_NOT_CFG;
178     }
179 
180     HOOK_DEL_IRQ_LOCK(intSave);
181 
182     while (OS_MHOOK_IS_VALID(*mHook)) {
183         if (*mHook == OS_MHOOK_NODE_DEAD) {
184             mHook++;
185             continue;
186         }
187 
188         if (*mHook == hook) {
189             // 可断言del为空
190             del = mHook;
191         }
192 
193         mHook++;
194         hookCnt++;
195     }
196 
197     if (del == NULL) {
198         HOOK_DEL_IRQ_UNLOCK(intSave);
199         return OS_ERRNO_HOOK_NOT_EXISTED;
200     }
201 
202     if ((hookCnt == 1) && (g_hookChgHandler[hookType] != NULL)) {
203         ret = g_hookChgHandler[hookType](hookType, HOOK_DEL_LAST);
204         if (ret != OS_OK) {
205             HOOK_DEL_IRQ_UNLOCK(intSave);
206             return ret;
207         }
208     }
209 
210     // 如果是最后一个,置为FREE,避免每次钩子调用遍历。 否则置为DEAD态。
211     if (OS_MHOOK_IS_VALID(*(del + 1))) {
212         *del = OS_MHOOK_NODE_DEAD;
213     } else {
214         *del-- = OS_HOOK_EMPTY;
215         while ((del >= g_hookCb[hookType].mulHook) && (*del == OS_MHOOK_NODE_DEAD)) {
216             *del-- = OS_HOOK_EMPTY;
217         }
218     }
219 
220     HOOK_DEL_IRQ_UNLOCK(intSave);
221     return OS_OK;
222 }
223 
224 /*
225  * 描述:钩子添加
226  */
OsHookAdd(enum HookType hookType,OsVoidFunc hook)227 OS_SEC_L4_TEXT U32 OsHookAdd(enum HookType hookType, OsVoidFunc hook)
228 {
229     if ((U32)hookType >= (U32)OS_HOOK_TYPE_NUM) {
230         return OS_ERRNO_HOOK_TYPE_INVALID;
231     }
232 
233     if (hook == NULL) {
234         return OS_ERRNO_HOOK_PTR_NULL;
235     }
236 
237     return OsMhookAdd((U32)hookType, hook);
238 }
239 
240 /*
241  * 描述:钩子删除
242  */
OsHookDel(enum HookType hookType,OsVoidFunc hook)243 OS_SEC_L4_TEXT U32 OsHookDel(enum HookType hookType, OsVoidFunc hook)
244 {
245     if ((U32)hookType >= (U32)(OS_HOOK_TYPE_NUM)) {
246         return OS_ERRNO_HOOK_TYPE_INVALID;
247     }
248 
249     if (hook == NULL) {
250         return OS_ERRNO_HOOK_PTR_NULL;
251     }
252 
253     return OsMhookDel((U32)hookType, hook);
254 }
255 
256 /*
257  * 描述:单钩子注册
258  */
OsShookReg(U32 hookType,OsVoidFunc hook)259 OS_SEC_L4_TEXT U32 OsShookReg(U32 hookType, OsVoidFunc hook)
260 {
261     uintptr_t intSave;
262     U32 ret = OS_OK;
263 
264     if (!OS_IS_SHOOK_TYPE(hookType)) {
265         return OS_ERRNO_HOOK_TYPE_INVALID;
266     }
267 
268     HOOK_ADD_IRQ_LOCK(intSave);
269 
270     if (hook == NULL) {  // unreg
271         if (g_hookCb[hookType].sigHook == NULL) {
272             HOOK_ADD_IRQ_UNLOCK(intSave);
273             return OS_OK;
274         }
275 
276         if (g_hookChgHandler[hookType] != NULL) {
277             ret = g_hookChgHandler[hookType](hookType, HOOK_DEL_LAST);
278         }
279 
280         if (ret == OS_OK) {
281             g_hookCb[hookType].sigHook = NULL;
282         }
283     } else {
284         if (g_hookCb[hookType].sigHook != NULL) {
285             HOOK_ADD_IRQ_UNLOCK(intSave);
286             return OS_ERRNO_HOOK_FULL;
287         }
288 
289         if (g_hookChgHandler[hookType] != NULL) {
290             ret = g_hookChgHandler[hookType](hookType, HOOK_ADD_FIRST);
291         }
292 
293         if (ret == OS_OK) {
294             g_hookCb[hookType].sigHook = hook;
295         }
296     }
297 
298     HOOK_ADD_IRQ_UNLOCK(intSave);
299     return ret;
300 }
301 
302 /*
303  * 描述:前置钩子添加
304  */
PRT_IdleAddPrefixHook(IdleHook hook)305 OS_SEC_L4_TEXT U32 PRT_IdleAddPrefixHook(IdleHook hook)
306 {
307     if (hook == NULL) {
308         return OS_ERRNO_SYS_PTR_NULL;
309     }
310 
311     return OsShookReg(OS_HOOK_IDLE_PREFIX, (OsVoidFunc)hook);
312 }
313