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