移植案例与原理 - startup子系统之bootstrap_lite部件 (2) 原创 精华
【本文正在参与优质创作者激励】
2.3 OHOS_SystemInit函数
函数OHOS_SystemInit()定义在文件base\startup\bootstrap_lite\services\source\system_init.c,代码如下。调用宏函数MODULE_INIT、SYS_INIT和函数SAMGR_Bootstrap()进行初始化启动。
void OHOS_SystemInit(void)
{
MODULE_INIT(bsp);
MODULE_INIT(device);
MODULE_INIT(core);
SYS_INIT(service);
SYS_INIT(feature);
MODULE_INIT(run);
SAMGR_Bootstrap();
}
我们详细分析下宏函数MODULE_INIT和SYS_INIT的源代码,这2个宏函数在文件base\startup\bootstrap_lite\services\source\core_main.h中定义,代码如下。这些宏函数的参数大都为name和step,name取值为bsp、device、core、service、feature、run,step取值为0。从⑺和⑻处可以看出,分别调用SYS_CALL、MODULE_CALL两个宏,第二个参数设置为0。⑸处定义的MODULE_BEGIN函数,用于返回链接脚本中定义的代码段的开始地址,当传入参数为bsp时,返回&__zinitcall_bsp_start,MODULE_BEGIN函数被展开为如下片段:
{ extern InitCall __zinitcall_sys_start; \
InitCall *initCall = &__zinitcall_bsp_start; \
(initCall); \
}
⑹处定义的MODULE_END函数,用于返回链接脚本中定义的代码段的结束地址,当传入参数为bsp时,返回&__zinitcall_bsp_end,MODULE_END函数被展开为如下片段:
{ extern InitCall __zinitcall_bsp_end; \
InitCall *initCall = &__zinitcall_bsp_end; \
(initCall); \
}
⑶和⑷处定义的SYS_BEGIN、SYS_END代码类似,分于返回链接脚本中定义的标记系统服务或特性的代码段的开始、结束地址,即&__zinitcall_sys_service_start、&__zinitcall_sys_service_end、&__zinitcall_sys_feature_start、&__zinitcall_sys_feature_end。⑴处定义的SYS_CALL函数,分别获取链接脚本中zInit代码段的开始initcall和结束地址initend,这些地址存放的是初始化函数的地址,语句 (*initcall)()会循环调用执行这些初始化函数。⑵处MODULE_CALL宏类似。
⑴ #define SYS_CALL(name, step) \
do { \
InitCall *initcall = (InitCall *)(SYS_BEGIN(name, step)); \
InitCall *initend = (InitCall *)(SYS_END(name, step)); \
for (; initcall < initend; initcall++) { \
(*initcall)(); \
} \
} while (0)
⑵ #define MODULE_CALL(name, step) \
do { \
InitCall *initcall = (InitCall *)(MODULE_BEGIN(name, step)); \
InitCall *initend = (InitCall *)(MODULE_END(name, step)); \
for (; initcall < initend; initcall++) { \
(*initcall)(); \
} \
} while (0)
......
⑶ #define SYS_BEGIN(name, step) \
({ extern InitCall __zinitcall_sys_##name##_start; \
InitCall *initCall = &__zinitcall_sys_##name##_start; \
(initCall); \
})
⑷ #define SYS_END(name, step) \
({ extern InitCall __zinitcall_sys_##name##_end; \
InitCall *initCall = &__zinitcall_sys_##name##_end; \
(initCall); \
})
⑸ #define MODULE_BEGIN(name, step) \
({ extern InitCall __zinitcall_##name##_start; \
InitCall *initCall = &__zinitcall_##name##_start; \
(initCall); \
})
⑹ #define MODULE_END(name, step) \
({ extern InitCall __zinitcall_##name##_end; \
InitCall *initCall = &__zinitcall_##name##_end; \
(initCall); \
})
⑺ #define SYS_INIT(name) \
do { \
SYS_CALL(name, 0); \
} while (0)
⑻ #define MODULE_INIT(name) \
do { \
MODULE_CALL(name, 0); \
} while (0)
3、 bootstrap_lite服务启动引导部件实现原理之bootstrap_service
在文件base\startup\bootstrap_lite\services\source\bootstrap_service.h中定义了2个宏函数INIT_APP_CALL和INIT_TEST_CALL,分别用来调用代码段&__zinitcall_app_XXX_start、&__zinitcall_app_XXX_end和&__zinitcall_test_start、&__zinitcall_test_end之间的初始化启动函数。bootstrap_service.h文件中的宏和base\startup\bootstrap_lite\services\source\core_main.h文件中的宏类似,不再一一分析。
3.1 结构体struct Bootstrap
在文件base\startup\bootstrap_lite\services\source\bootstrap_service.c中定义了结构体struct Bootstrap,如下代码⑵处。其中结构体中的INHERIT_SERVICE定义在文件foundation/distributedschedule/samgr_lite/interfaces/kits/samgr/service.h,见代码片段⑴处。
⑴ #define INHERIT_SERVICE \
const char *(*GetName)(Service * service); \
BOOL (*Initialize)(Service * service, Identity identity); \
BOOL (*MessageHandle)(Service * service, Request * request); \
TaskConfig (*GetTaskConfig)(Service * service)
......
⑵ typedef struct Bootstrap {
INHERIT_SERVICE;
Identity identity;
uint8 flag;
} Bootstrap;
结构体Identity定义在文件foundation\distributedschedule\samgr_lite\interfaces\kits\samgr\message.h中,用于标识一个服务或特性。
/**
* @brief Identifies a service and feature.
*
* You can use this structure to identity a {@link IUnknown} feature to which messages will be
* sent through the asynchronous function of {@link IUnknown}. \n
*
*/
struct Identity {
/** Service ID */
int16 serviceId;
/** Feature ID */
int16 featureId;
/** Message queue ID */
MQueueId queueId;
};
3.2 Init(void)函数
讲解移植适配示例时,我们已经知道,bootstrap_lite部件会编译//base/startup/bootstrap_lite/services/source/bootstrap_service.c,该文件通过函数宏SYS_SERVICE_INIT将Init()函数符号灌段到__zinitcall_sys_service_start和__zinitcall_sys_service_end代码段中,代码片段如下。下文再详细分析GetName、Initialize、MessageHandle和GetTaskConfig函数。
static const char *GetName(Service *service);
static BOOL Initialize(Service *service, Identity identity);
static TaskConfig GetTaskConfig(Service *service);
static BOOL MessageHandle(Service *service, Request *request);
static void Init(void)
{
static Bootstrap bootstrap;
bootstrap.GetName = GetName;
bootstrap.Initialize = Initialize;
bootstrap.MessageHandle = MessageHandle;
bootstrap.GetTaskConfig = GetTaskConfig;
bootstrap.flag = FALSE;
SAMGR_GetInstance()->RegisterService((Service *)&bootstrap);
}
SYS_SERVICE_INIT(Init);
3.3 GetName和Initialize函数
GetName函数代码如下,其中BOOTSTRAP_SERVICE定义在文件foundation\distributedschedule\samgr_lite\interfaces\kits\samgr\samgr_lite.h中,取值为"Bootstrap",表示启动引导服务。
static const char *GetName(Service *service)
{
(void)service;
return BOOTSTRAP_SERVICE;
}
Initialize函数定义如下,用于设置启动引导服务的标识信息。
static BOOL Initialize(Service *service, Identity identity)
{
Bootstrap *bootstrap = (Bootstrap *)service;
bootstrap->identity = identity;
return TRUE;
}
3.4 MessageHandle函数和GetTaskConfig函数
MessageHandle函数和GetTaskConfig函数代码如下,MessageHandle函数用于处理各种请求,请求消息编号定义request->msgId定义在文件foundation\distributedschedule\samgr_lite\interfaces\kits\samgr\samgr_lite.h中的枚举enum BootMessage,如下⑴处所示。在MessageHandle函数中,当请求的消息编号为BOOT_SYS_COMPLETED系统服务初始化完成时,检查应用服务是否加载。当应用没有加载时,执行INIT_APP_CALL宏函数调用zInit代码段上的应用服务和应用特性初始化函数。然后执行⑶,调用函数SAMGR_SendResponseByIdentity进行响应。GetTaskConfig函数用于获取任务配置。
⑴ typedef enum BootMessage {
/** Message indicating that the core system service is initialized */
/** 标识核心系统服务初始化完成 */
BOOT_SYS_COMPLETED,
/** Message indicating that the system and application-layer services are initialized */
/** 标识应用层服务初始化完成 */
BOOT_APP_COMPLETED,
/** Message indicating service registration during running */
/** 标识运行时的服务注册 */
BOOT_REG_SERVICE,
/** Maximum number of message IDs */
/** 标识消息最大值,butt是烟蒂;屁股;枪托的意思,表示尾部吧 */
BOOTSTRAP_BUTT
} BootMessage;
......
static BOOL MessageHandle(Service *service, Request *request)
{
Bootstrap *bootstrap = (Bootstrap *)service;
switch (request->msgId) {
case BOOT_SYS_COMPLETED:
⑵ if ((bootstrap->flag & LOAD_FLAG) != LOAD_FLAG) {
INIT_APP_CALL(service);
INIT_APP_CALL(feature);
bootstrap->flag |= LOAD_FLAG;
}
⑶ (void)SAMGR_SendResponseByIdentity(&bootstrap->identity, request, NULL);
break;
case BOOT_APP_COMPLETED:
(void)SAMGR_SendResponseByIdentity(&bootstrap->identity, request, NULL);
break;
case BOOT_REG_SERVICE:
(void)SAMGR_SendResponseByIdentity(&bootstrap->identity, request, NULL);
break;
default:
break;
}
return TRUE;
}
static TaskConfig GetTaskConfig(Service *service)
{
(void)service;
// The bootstrap service uses a stack of 2 KB (0x800) in size and a queue of 20 elements.
// You can adjust it according to the actual situation.
TaskConfig config = {LEVEL_HIGH, PRI_NORMAL, 0x800, 20, SHARED_TASK};
return config;
}
参考站点
- OpenHarmony / startup_bootstrap_lite
- HarmonyOS Device > 文档 > 指南 > 基础能力: bootstrap服务启动组件
- 启动恢复子系统.md
- 轻量带屏解决方案之恒玄芯片移植案例
小结
本文介绍了startup子系统之bootstrap_lite服务启动引导部件的移植适配案例及原理。因为时间关系,仓促写作,或能力限制,若有失误之处,请各位读者多多指正。感谢阅读,有什么问题,请留言。
【本文正在参与优质创作者激励】