uboot与kernel分析随手笔记

编程入门 行业动态 更新时间:2024-10-10 00:30:24

uboot与kernel分析随手<a href=https://www.elefans.com/category/jswz/34/1770047.html style=笔记"/>

uboot与kernel分析随手笔记

先声明此笔记是本人观看达内游宏伟老师视频撰写由于使用的内核源码与uboot不同可能有所不一样
uboot

两个板子外设不一样但是CPU相同处理方法
第一步明确代码执行流程然后根据要求修改,就是寻找入口函数
有两种方法一是通过makefile或者通过连接脚本寻找
在编译时使用如下指令	make V=1	输出编译信息在编译信息中寻找连接信息
打印如下信息
arm-linux-gnueabihf-ld.bfd   -pie  --gc-sections -Bstatic -Ttext 0x87800000 -o u-boot -T u-boot.lds
找到连接信息如下-T u-boot.lds
uboot运行起始地址为0x87800000 
通过find命令找到连接文件./u-boot.lds
z@z-virtual-machine:~/uboot$ find . -name *.lds
./board/tqc/tqm8xx/u-boot.lds
./board/compulab/cm_t335/u-boot.lds
./board/ti/am335x/u-boot.lds
./board/birdland/bav335x/u-boot.lds
./board/freescale/mx31ads/u-boot.lds
./board/renesas/sh7752evb/u-boot.lds
./board/renesas/sh7757lcr/u-boot.lds
./board/renesas/sh7753evb/u-boot.lds
./board/cirrus/edb93xx/u-boot.lds
./board/vscom/baltos/u-boot.lds
./u-boot.lds
./arch/sh/cpu/u-boot.lds
./arch/nios2/cpu/u-boot.lds
./arch/nds32/cpu/n1213/u-boot.lds
./arch/microblaze/cpu/u-boot.lds
./arch/mips/cpu/u-boot.lds
./arch/blackfin/cpu/u-boot.lds
./arch/x86/cpu/u-boot.lds
./arch/arm/mach-zynq/u-boot.lds
./arch/arm/cpu/armv8/u-boot.lds
./arch/arm/cpu/u-boot.lds
./arch/arc/cpu/u-boot.lds
./arch/avr32/cpu/u-boot.lds
./arch/sandbox/cpu/u-boot.lds
./arch/powerpc/cpu/mpc86xx/u-boot.lds
./arch/powerpc/cpu/mpc5xxx/u-boot.lds
./arch/powerpc/cpu/ppc4xx/u-boot.lds
./arch/powerpc/cpu/mpc83xx/u-boot.lds
./arch/powerpc/cpu/mpc512x/u-boot.lds
./arch/powerpc/cpu/mpc5xx/u-boot.lds
./arch/powerpc/cpu/mpc8260/u-boot.lds
./arch/powerpc/cpu/mpc85xx/u-boot.lds
./arch/m68k/cpu/u-boot.lds
./arch/openrisc/cpu/u-boot.lds
./arch/sparc/cpu/u-boot.lds
接下来对./u-boot.lds进行分析这里我只粘贴部分
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{. = 0x00000000;. = ALIGN(4);.text :{*(.__image_copy_start)*(.vectors)arch/arm/cpu/armv7/start.o (.text*)*(.text*)}. = ALIGN(4);.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }. = ALIGN(4);.data : {*(.data*)}. = ALIGN(4);. = .;. = ALIGN(4);.u_boot_list : {KEEP(*(SORT(.u_boot_list*)));}
分析uboot入口为_start
根据arch/arm/cpu/armv7/start.o (.text*)分析到路径下观看发现是一个arch/arm/cpu/armv7/start.S汇编文件注意这个可以有多个按顺序进入。
.globl	reset.globl	save_boot_params_retreset:/* Allow the board to save important registers */b	save_boot_params
save_boot_params_ret:/** disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,* except if in HYP mode already*/mrs	r0, cpsrand	r1, r0, #0x1f		@ mask mode bitsteq	r1, #0x1a		@ test for HYP modebicne	r0, r0, #0x1f		@ clear all mode bitsorrne	r0, r0, #0x13		@ set SVC modeorr	r0, r0, #0xc0		@ disable FIQ and IRQmsr	cpsr,r0/** Setup vector:* (OMAP4 spl TEXT_BASE is not 32 byte aligned.* Continue to use ROM code vector only in OMAP4 spl)*/
#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD))/* Set V=0 in CP15 SCTLR register - for VBAR to point to vector */mrc	p15, 0, r0, c1, c0, 0	@ Read CP15 SCTLR Registerbic	r0, #CR_V		@ V = 0mcr	p15, 0, r0, c1, c0, 0	@ Write CP15 SCTLR Register/* Set vector address in CP15 VBAR register */ldr	r0, =_startmcr	p15, 0, r0, c12, c0, 0	@Set VBAR
#endif/* the mask ROM code should have PLL and others stable */
#ifndef CONFIG_SKIP_LOWLEVEL_INITbl	cpu_init_cp15bl	cpu_init_crit
#endifbl	_main/*------------------------------------------------------------------------------*/ENTRY(c_runtime_cpu_setup)
在这个找到三个跳转函数但是我没有找到我想要的sh_generic_init但是可能隐藏到哪里了
最后会进入我们下面看到的函数我们不必了解主要看for循化调用指针初始化
void sh_generic_init(void)
{bd_t *bd;init_fnc_t **init_fnc_ptr;memset(gd, 0, GENERATED_GBL_DATA_SIZE);gd->flags |= GD_FLG_RELOC;	/* tell others: relocation done */gd->bd = (bd_t *)(gd + 1);	/* At end of global data */gd->baudrate = CONFIG_BAUDRATE;gd->cpu_clk = CONFIG_SYS_CLK_FREQ;bd = gd->bd;bd->bi_memstart	= CONFIG_SYS_SDRAM_BASE;bd->bi_memsize = CONFIG_SYS_SDRAM_SIZE;
#ifndef CONFIG_SYS_NO_FLASHbd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
#endif
#if defined(CONFIG_SYS_SRAM_BASE) && defined(CONFIG_SYS_SRAM_SIZE)bd->bi_sramstart = CONFIG_SYS_SRAM_BASE;bd->bi_sramsize	= CONFIG_SYS_SRAM_SIZE;
#endiffor (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {WATCHDOG_RESET();if ((*init_fnc_ptr) () != 0)hang();}#ifdef CONFIG_WATCHDOG/* disable watchdog if environment is set */{char *s = getenv("watchdog");if (s != NULL)if (strncmp(s, "off", 3) == 0)WATCHDOG_DISABLE();}
#endif /* CONFIG_WATCHDOG*/#ifdef CONFIG_BITBANGMIIbb_miiphy_init();
#endif
#if defined(CONFIG_CMD_NET)puts("Net:   ");eth_initialize();
#endif /* CONFIG_CMD_NET */while (1) {WATCHDOG_RESET();main_loop();}
}
typedef int (init_fnc_t) (void)
init_fnc_t *init_sequence[] =
{cpu_init,		/* basic cpu dependent setup */board_init,		/* basic board dependent setup */interrupt_init,	/* set up exceptions */env_init,		/* event init */serial_init,	/* SCIF init */INIT_FUNC_WATCHDOG_INIT	/* watchdog init */console_init_f,display_options,checkcpu,checkboard,		/* Check support board */dram_init,		/* SDRAM init */timer_init,		/* SuperH Timer (TCNT0 only) init */sh_mem_env_init,
#ifndef CONFIG_SYS_NO_FLASHsh_flash_init,	/* Flash memory init*/
#endifINIT_FUNC_NAND_INIT/* Flash memory (NAND) init */INIT_FUNC_PCI_INIT	/* PCI init */stdio_init,console_init_r,interrupt_init,
#ifdef CONFIG_BOARD_LATE_INITboard_late_init,
#endif
#if defined(CONFIG_CMD_MMC)sh_mmc_init,
#endifNULL			/* Terminate this list */
};
//for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {WATCHDOG_RESET();if ((*init_fnc_ptr) () != 0)hang();}详细分析这里定义了一个函数指针并且用此函数指针定义了一个指针数组接下来我们就可以通过for循环调用数组里面的函数来进行初始化,如果我们需添加自己的初始化程序直接在后面添加即可。
一些主要的宏定义/uboot/include/configs/ABC.h
里面包含了一些外部硬件初始化信息串口波特率等等
/** Memory Info*/
/* malloc() len */
#define CONFIG_SYS_MALLOC_LEN		(0x10000 + 512 * 1024)
/* memtest start address */
#define CONFIG_SYS_MEMTEST_START	0xA0000000
#define CONFIG_SYS_MEMTEST_END		0xA1000000	/* 16MB RAM test */
#define CONFIG_NR_DRAM_BANKS	1		/* we have 1 bank of DRAM */
#define PHYS_SDRAM_1		0xA0000000	/* DDR Start */
#define PHYS_SDRAM_1_SIZE	0x08000000	/* DDR size 128MB *//** Serial Driver info*/
#define CONFIG_MXC_UART
#define CONFIG_MXC_UART_BASE	UART1_BASE
#define CONFIG_CONS_INDEX	1		/* use UART0 for console */
#define CONFIG_BAUDRATE		115200		/* Default baud rate *//** Flash & Environment*/
#define CONFIG_ENV_IS_IN_FLASH
#define CONFIG_FLASH_CFI_DRIVER
#define CONFIG_SYS_FLASH_CFI
/* Use buffered writes (~10x faster) */
#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE	1
/* Use hardware sector protection */
#define CONFIG_SYS_FLASH_PROTECTION		1
#define CONFIG_SYS_MAX_FLASH_BANKS	1	/* max number of flash banks */
/* CS2 Base address */
#define PHYS_FLASH_1			0xc0000000
/* Flash Base for U-Boot */
#define CONFIG_SYS_FLASH_BASE		PHYS_FLASH_1
#define CONFIG_SYS_MAX_FLASH_SECT	(PHYS_FLASH_SIZE / \CONFIG_SYS_FLASH_SECT_SZ)
#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_FLASH_BASE
#define CONFIG_SYS_MONITOR_LEN		0x40000		/* Reserve 256KiB */
#define CONFIG_ENV_SIZE		CONFIG_ENV_SECT_SIZE
/* Address and size of Redundant Environment Sector	*/
#define CONFIG_ENV_OFFSET_REDUND	(CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
#define CONFIG_ENV_SIZE_REDUND	CONFIG_ENV_SIZE/** Ethernet*/
#define CONFIG_FEC_MXC
#define CONFIG_FEC_MXC_PHYADDR		0x1f
#define CONFIG_MII
大概能一看就了解不详细解释。
#define CONFIG_ENV_OFFSET		0x180000 /* environment starts here */环境变量存储其实位置
#define CONFIG_ENV_ADDR_REDUND		(CONFIG_ENV_OFFSET + CONFIG_SYS_ENV_SECT_SIZE)	环境变量存储位置大小
#define CONFIG_ENV_SIZE_REDUND		(CONFIG_ENV_SIZE)
 kernel编译前先到System Type  --->下 ARM system type (Allow multiple platforms to be selected)  ---> 观察此内核源码是否支持ARM架构Boot options  ---> 到启动选项下检查(noinitrd console=ttymxc0,115200) Default kernel command string   内核启动自己传递的参数信息。  Kernel command line type (Use bootloader kernel arguments if available)  --->此选项用于选择内核启动参数来自自己还是uboot还是同时使用。Use bootloader kernel arguments if available  使用uboot启动传递参数  Extend bootloader kernel arguments  在内核传递参数后追加uboot参数Always use the default kernel command string  使用内核自己的传递参数Device Drivers  --->Memory Technology Device (MTD) support  --->norflash与nandflash的驱动Mapping drivers for chip access  --->norflash驱动NAND Device Support  --->nandflash驱动Network device support  ---> 网卡驱动Ethernet team driver support  ---->Input device support  --->输入设备驱动I2C support  --->IIC驱动I2C Hardware Bus support  ---> Multimedia support  ---> 多媒体驱动例如摄像头Graphics support  --->显卡驱动File systems  --->文件系统The Extended 4 (ext4) filesystemEXT4文件系统DOS/FAT/NT Filesystems  --->VFAT (Windows-95) fs support	//FAT32文件系统NTFS file system support	//NTFS文件系统例如移动硬盘Miscellaneous filesystems  ---> Compressed ROM file system support (cramfs) (OBSOLETE) 	//cramfs文件系统
内核源码与硬件相关信息
如果内核包含设备树那么路径为
arch/arm/mach-xxx/devices/下分为单个文件编写
如果不包含设备树路径为
arch/arm/plat-xxxx/xxxx/device.c中
其中里面主要记录了一些设备的地址信息等
/* Regulators */
static struct regulator_init_data gpo_init = {.constraints = {.boot_on = 1,.always_on = 1,}
};static struct regulator_consumer_supply vmmc1_consumers[] = {REGULATOR_SUPPLY("vcore", "spi0.0"),REGULATOR_SUPPLY("cmos_2v8", "soc-camera-pdrv.0"),
};static struct regulator_init_data vmmc1_init = {.constraints = {.min_uV	= 2800000,.max_uV = 2800000,.apply_uV = 1,.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |REGULATOR_CHANGE_STATUS,},.num_consumer_supplies = ARRAY_SIZE(vmmc1_consumers),.consumer_supplies = vmmc1_consumers,
};static struct regulator_consumer_supply vgen_consumers[] = {REGULATOR_SUPPLY("vdd", "spi0.0"),
};static struct regulator_init_data vgen_init = {.constraints = {.min_uV	= 1800000,.max_uV = 1800000,.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,},.num_consumer_supplies = ARRAY_SIZE(vgen_consumers),.consumer_supplies = vgen_consumers,
};static struct regulator_consumer_supply vvib_consumers[] = {REGULATOR_SUPPLY("cmos_vcore", "soc-camera-pdrv.0"),
};
如何在内核菜单中添加自己的选项
Kconfig功能是生成菜单选项
常用关键字
config:生成菜单选项
tristate:此菜单选项操作方法Y键选为* M键选中为M N键不选
bool:指示此菜单有两种操作方式Y键选为*  N键不选
help:此菜单的帮助信息
Y键选为*	表示选中对应的源代码与uImage编译到一起
M键选中为M 	表示选中但是与uImage分开编译
N键不选	不选
config	 HELLO_WORLDtristate "hello,world"help"this is atest msg"
解释
config	 HELLO_WORLD	最终生成一个菜单选项名称为CONFIG_HELLO_WORLDtristate "hello,world"help"this is atest msg"
Makefile文件如何使用config文件
使用格式:obj-$(CONFIG_) +=源文件.o
Y键选为*	表示选中对应的源代码与uImage编译到一起
obj-y +=源文件.o
M键选中为M 	表示选中但是与uImage分开编译
obj-m +=源文件.o
N键不选	不选
添加编译选项流程
1.建新文件
2.拷贝到内核源码下
3.添加当前路径下Kconfig配置菜单

source "drivers/android/Kconfig"config TTTTTTTtristate "AAAAAAAAAAAA"help "asdsadsad"endmenu
4.修改同级目录下Makefile文件

obj-$(CONFIG_GENERIC_PHY)	+= phy/
obj-$(CONFIG_TTTTTTT) += my_led.o
根文件系统制作成.img文件
到根文件系统路径下
sudo dd if=/dev/zero of=rootfs_ext4.img bs=1k count=8196
sudo 
dd 	用于创建一个单个镜像文件
if=/dev/zero	将创建的单个镜像文件里面的内容全部来自/dev/zero/这个设备源源不断产生0
of=rootfs_ext4.img	指定生成文件名字并且向里面写入数据全为0 
bs=1k 	以块为单位一块大小为1024字节
count=8196	生成的数据块大小为8M
格式化文件
sudo mkfs.ext4 rootfs_ext4.img
创建一个目录
sudo mkdir /mnt/initrd
将文件挂接到创建目录下
sudo mount -t ext4 -o loop rootfs_ext4.img /mnt/initrd
将根文件系统拷贝到挂接目录下
cp /rootfs/* /mnt/initrd -frd
卸载挂接
sudo umount /mnt/initrd

更多推荐

uboot与kernel分析随手笔记

本文发布于:2024-03-13 17:28:14,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1734473.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:笔记   uboot   kernel

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!