Android编译传递宏定义到lk和kernel的c文件

本文详细介绍了如何在Android编译环境中将宏定义传递给lk和kernel的c文件。方法一是通过不同project配置文件,通过修改BoardConfig.mk文件并创建新的project配置,将宏定义添加到lk和kernel的编译选项中。方法二是同一project下,通过Android.mk文件直接传递宏定义给lk和kernel的Makefile,然后在Makefile中添加条件编译指令。此外,还讨论了在preloader中使用宏来区分不兼容DDR编译的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

方式1:通过不同project配置文件传递

一般在Android的主目录,device目录下,不同board工程目录里,有“BoardConfig.mk”文件,一般会有两个宏:

LK_PROJECT := yangtutu
KERNEL_DEFCONFIG := yangtutu_defconfig

第一个“LK_PROJECT”的值,代表的是,编译lk的时候,使用lk主目录下,project目录中的“yangtutu.mk”配置文件来编译,在这个文件中,定义的“DEFINES += CONFIG_YANGTUTU”,可以把宏“CONFIG_YANGTUTU”传递给lk下面的c文件;

第二个“KERNEL_DEFCONFIG”的值,代表的是,编译kernel的时候,使用kernel主目录下,arch目录中,configs中的对应“yangtutu_defconfig”和“yangtutu_debug_defconfig”配置文件来编译,在这个配置文件中定义的“CONFIG_YANGTUTU=y”,可以把这个宏传递给kernel下的Makefile文件,在对应c文件的Makefile文件中添加“ccflags-$(CONFIG_YANGTUTU) += -DCONFIG_YANGTUTU”,就可以把宏“CONFIG_YANGTUTU”传递给kernel下的c文件。

例如,现在需要传递新的宏“CONFIG_YANGTUTU_NEW”到c文件,步骤如下:
1.在“BoardConfig.mk”文件的“LK_PROJECT”和“KERNEL_DEFCONFIG”宏之前,定义一个宏“YANGTUTU_NEW := yes”,或者在Android源码目录执行“make”的时候,带上这个参数,如:make -j10 YANGTUTU_NEW=yes ;
2.在“BoardConfig.mk”文件中“LK_PROJECT”和“KERNEL_DEFCONFIG”宏最后赋值的地方做判断,并新增project “yangtutu_new”,如下:

ifeq (yes, $(YANGTUTU_NEW))
LK_PROJECT := yangtutu_new
KERNEL_DEFCONFIG := yangtutu_new_defconfig
else
LK_PROJECT := yangtutu
KERNEL_DEFCONFIG := yangtutu_defconfig
endif

3.在lk的project目录下,新增“yangtutu_new.mk”配置文件(可以从“yangtutu.mk”直接拷贝),并在文件中添加:DEFINES += CONFIG_YANGTUTU_NEW,这下就可以在lk的c文件中使用宏“CONFIG_YANGTUTU_NEW”了;
4.在kernel的configs目录下,新增“yangtutu_new_defconfig”和“yangtutu_new_debug_defconfig”配置文件,并在文件中添加:CONFIG_YANGTUTU_NEW=y,然后在合适的“Kconfig”文件里添加:config YANGTUTU_NEW,在合适的“Makefile”文件里添加:ccflags-$(CONFIG_YANGTUTU_NEW) += -DCONFIG_YANGTUTU_NEW,就可以在对应的c文件中使用宏“CONFIG_YANGTUTU_NEW”了;

上面的方式需要新建一个project,比较适用于两个不用的project,有同一个宏,但是有不一样的值,需要区分开的时候。下面是一种不用区分project的方式,直接传递。

方式2:同一个project下,通过makefile传递

对于lk,Android编译的时候,会先调用lk主目录下的“Android.mk”文件,这个文件可以用到当前Android编译环境中的所用宏,这个文件中有如下代码:

LOCAL_PATH := $(call my-dir)

LK_DIR := $(LOCAL_PATH)
LK_MAKE_OPTION := $(if $(SHOW_COMMANDS),NOECHO=) $(if $(LK_CROSS_COMPILE),TOOLCHAIN_PREFIX=$(LK_CROSS_COMPILE)) BOOTLOADER_OUT=$(TARGET_LK_OUT) ROOTDIR=$(LK_ROOT_DIR) CONFIG_YANGTUTU=$(YANGTUTU)

$(MAKE) -C $(LK_DIR) $(LK_MAKE_OPTION) $(LK_PROJECT)

可以看到最终编译是执行“$(MAKE)”,这个会执行lk目录下的“makefile”文件;“MAKE”后面带的“LK_MAKE_OPTION”的值,会做为参数传给“makefile”文件,然后在“makefile”文件中,用“LK_MAKE_OPTION”传递的“CONFIG_YANGTUTU”做判断:

ifeq ($(CONFIG_YANGTUTU),yes)
  CFLAGS += -DCONFIG_YANGTUTU
endif

通过“CFLAGS += -DCONFIG_YANGTUTU”,可以把宏“CONFIG_YANGTUTU”传给lk的c文件;

对于kernel,也是类似的流程,在kernel根目录下,有“Android.mk”文件,同样是执行“$(MAKE)”,不过传递的是“KERNEL_MAKE_OPTION”的值,这个“KERNEL_MAKE_OPTION”在kernel根目录下的“kenv.mk”文件中:

KERNEL_MAKE_OPTION := O=$(KERNEL_OUT) ARCH=$(TARGET_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) ROOTDIR=$(KERNEL_ROOT_DIR) $(if $(strip $(SHOW_COMMANDS)),V=1) CONFIG_YANGTUTU=$(YANGTUTU)

然后也是执行kernel根目录下的“Makefile”,不过需要使用“KBUILD_CFLAGS += -DCONFIG_YANGTUTU”,如下:

ifeq ($(CONFIG_YANGTUTU),yes)
  KBUILD_CFLAGS += -DCONFIG_YANGTUTU
endif

把宏“CONFIG_YANGTUTU”传给kernel的c文件。

例如,现在需要传递新的宏“CONFIG_YANGTUTU_NEW”到c文件,步骤如下:
1.在“BoardConfig.mk”文件或者其他在Android编译环境下的mk文件中,添加一个宏“YANGTUTU_NEW := yes”,或者在Android源码目录执行“make”的时候,带上这个参数,如:make -j10 YANGTUTU_NEW=yes ;
2.修改lk根目录下的“Android.mk”文件中的“LK_MAKE_OPTION”,在最后增加“CONFIG_YANGTUTU_NEW=$(YANGTUTU_NEW)”,如下:

LK_MAKE_OPTION := $(if $(SHOW_COMMANDS),NOECHO=) $(if $(LK_CROSS_COMPILE),TOOLCHAIN_PREFIX=$(LK_CROSS_COMPILE)) BOOTLOADER_OUT=$(TARGET_LK_OUT) ROOTDIR=$(LK_ROOT_DIR) CONFIG_YANGTUTU=$(YANGTUTU) CONFIG_YANGTUTU_NEW=$(YANGTUTU_NEW)

3.修改lk根目录下的“makefile”文件,在合适的位置增加如下内容:

ifeq ($(CONFIG_YANGTUTU_NEW),yes)
  CFLAGS += -DCONFIG_YANGTUTU_NEW
endif

4.修改kernel根目录下的“kenv.mk”文件中的“KERNEL_MAKE_OPTION”,在最后增加“CONFIG_YANGTUTU_NEW=$(YANGTUTU_NEW)”,如下:

KERNEL_MAKE_OPTION := O=$(KERNEL_OUT) ARCH=$(TARGET_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) ROOTDIR=$(KERNEL_ROOT_DIR) $(if $(strip $(SHOW_COMMANDS)),V=1) CONFIG_YANGTUTU=$(YANGTUTU) CONFIG_YANGTUTU_NEW=$(YANGTUTU_NEW)

5.修改kernel目录下的“Makefile”文件,在合适的地方增加如下内容:

ifeq ($(CONFIG_YANGTUTU_NEW),yes)
  KBUILD_CFLAGS += -DCONFIG_YANGTUTU_NEW
endif

这种方式,可以在不用区分project的情况下,让lk和kernel的源码都能使用到这个宏!

preloader用宏来区分无法兼容的DDR的编译

两种办法:
1.像上面一样,通过“Android.mk”文件的“PRELOADER_MAKE_OPTION”传宏进去,然后在“custom_MemoryDevice.h”头文件用宏控制不同的DDR编译;
2.在 preloader/tools/emigen/emigen.mk 文件中,使用“Android.mk”传进来的宏,对“CUSTOM_MEMORY_HDR”变量做区分,如下:

ifeq ($(CONFIG_DDR_NEW),yes)
CUSTOM_MEMORY_HDR := $(MTK_PATH_CUSTOM)/inc/custom_MemoryDevice_new.h
else
CUSTOM_MEMORY_HDR := $(MTK_PATH_CUSTOM)/inc/custom_MemoryDevice.h
endif

使用不同的h文件,控制不同的DDR编译。
这种方式下,如果要在“emigen.mk”中直接使用“Android.mk”传进来的宏,需要在preloader根目录下的“Makefile”文件中增加:export CONFIG_DDR_NEW ,将宏导出!

<think>好的,我现在需要帮助用户找到关于MediaTek LK(Loader Kernel)的开发文档教程。首先,我得回忆一下用户之前提供的参考资料,看看有没有相关的信息。用户提到了几个引用,其中引用[2]、[3]、[4]、[5]都涉及LK的启动流程、代码结构以及内存布局等内容。这些信息可能对构建答案有帮助。 首先,用户的问题是关于MTK LK的技术资料或教程,但根据提供的引用,用户可能已经接触过一些LK的代码,比如在bootstrap2函数中的platform_init()apps_init(),以及内存段的定义。这说明用户可能需要更深入的开发文档或官方资源。 接下来,我需要考虑MTK LK的官方资料通常在哪里。一般来说,联发科可能会将相关文档提供给合作伙伴或客户,而不是完全公开。因此,普通开发者可能难以获取完整的文档。这种情况下,可能需要依赖开源代码、社区资源或第三方教程。 查看用户提供的引用,引用[5]提到了链接脚本中的内存布局,这可能意味着用户需要了解LK的内存管理部分。此外,引用[3]中的代码流程显示LK负责硬件初始化、启动模式选择等,这些属于LK的核心功能。因此,在回答中应该涵盖LK的主要职责关键流程。 用户可能需要具体的步骤或资源链接,但考虑到公开资料的有限性,可能需要建议他们查阅MTK的官方资源,如Open Source Release Portal,或者社区论坛如XDA Developers。此外,LK的源码分析也是一个重要的学习途径,比如分析platform_init()apps_init()函数,以及启动流程中的各个阶段。 另外,用户提供的引用[4]提到了修改的文件路径,这可能表明用户正在进行LK的定制开发,因此需要了解如何修改配置LK的代码。在回答中,可以建议用户查看这些文件的结构,理解各模块的作用,比如cust_bldr.makmt_boot.c。 还需要注意用户提到的内存布局问题,在引用[5]中,用户询问了__apps_start__apps_end的定义,这涉及到链接脚本的知识。因此,在回答中应提到编译链接原理内存布局,引导用户查看相关的.ld文件,如system-onesegment.ld。 最后,生成相关问题时要围绕LK的开发、启动流程、内存管理、调试方法等,帮助用户进一步探索这个主题。</think>关于MediaTek LK(Loader Kernel)的开发文档教程,以下是技术实现路径分析及建议: ### 1. LK的核心功能 MTK LK是介于BootROMLinux Kernel之间的轻量级引导程序,主要职责包括: - 硬件初始化(时钟、DDR、存储设备等)[^3] - 设备树(DTB)解析内核启动参数准备[^1] - 安全启动验证固件加载[^2] - 多阶段引导控制(preloader→lkkernel)[^4] ### 2. 关键代码结构 ``` bootable/bootloader/lk/ ├── app/ # 各平台引导逻辑 │ └── mt_boot/ # MTK平台特有实现 ├── arch/ # 架构相关代码 ├── platform/ # 平台级驱动 └── kernel/ # 微型内核框架 ``` 关键文件示例: ```c // mt_boot.c中的启动流程 void mt_boot_init() { platform_early_init(); // 时钟/UART初始化 target_init(); // 存储设备检测 load_kernel_image(); // 从存储加载内核 prepare_cmdline(); // 构造内核启动参数 boot_linux(); // 跳转到kernel_entry[^3] } ``` ### 3. 开发资源获取 - **官方资源**:需通过MediaTek Open Source Release Portal申请访问权限(通常需要OEM授权) - **代码分析**:通过AOSP代码库研究LK实现: ```shell git clone https://android.googlesource.com/platform/bootable/bootloader/legacy ``` - **调试方法**: - 通过UART日志分析启动流程 - 使用`make DEBUG=1`编译生成调试符号 - 关键宏定义追踪: ```c #define dprintf(lvl, x...) do { if (lvl <= DEBUGLEVEL) printf(x); } while (0) ``` ### 4. 内存布局分析 链接脚本定义内存区域(示例): ``` ./lk/arch/arm/system-onesegment.ld .rodata : { __apps_start = .; // 应用段起始地址 KEEP(*(.apps)) // 应用代码段 __apps_end = .; // 应用段结束地址[^5] } ``` 该设计实现代码段隔离,保证引导程序的可靠性。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值