Linux kernel porting

Linux kernel porting

Busy with papers, I don’t have time to write a blog and take notes. I don’t want to do papers on Friday, and record the following recent Linux kernel books.

Linux kernel boot process

Before transplanting Linux, first understand its boot process. The boot process of Linux is divided into two parts: the boot process related to the architecture/development board and the subsequent general boot process . The following figure shows the startup process of the Linux kernel vmlinux on the ARM architecture processor. The reason for emphasizing vmlinux is that kernels of other formats will have some unique operations before performing the same processes as vmlinux. For example, corresponding to the compressed kernel zImage, it first self-extracts to get vmlinux, and then executes vmlinux to start the "normal" startup process.
The boot phase is usually written in assembly language. It first checks whether the kernel supports the processor of the current architecture, and then checks whether it supports the current development board. After passing the check, it is ready to call the start_kernel function of the next stage. This is mainly divided into the following two steps:

  • (1) The virtual address used when connecting to the kernel, so it is necessary to set the page table and enable the MMU.
  • (2) Routine work before calling the C function start_kernel, including copying the data segment, clearing the BSS segment, and calling the start_kernel function.
    The key code of the second stage is mainly written in C language. It performs all the work of kernel initialization, and finally calls the rest_init function to start the init process, creating the first process of the system: the init process. In the second stage, there are still some architecture/development board related codes. As shown in the figure below, the setup_arch function is used to set the architecture/development board related settings (such as resetting the page table, setting the system clock, initializing the serial port, etc.).
    Insert picture description here

Modify the kernel to support S3C2410/S3C2440 development board

  • First configure and compile the kernel to ensure that the kernel can be compiled correctly. After getting the kernel source code, first modify the top-level Makefile
185 ARCH ?= $(SUBARCH)
186 CROSS_COMPILE ?=
改为
185 ARCH ?= arm
186 CROSS_COMPILE ?= arm-linux-
  • Then execute the following command, use the arch/arm/configs/S3C2410_defconfig file to configure the kernel, it generates the .config configuration file, and then you can directly use "make menuconfig" to modify the configuration
make smdk2401_defconfig
  • Finally compile and generate the kernel, execute "make" to generate the kernel image file vmlinux in the top directory; execute "make uImage" in addition to generating vmlinux, but also generate the U-Boot format kernel image file uImage under the arch/arm/boot/ directory. We use "make uImae"
  • For S3C2410 development board, uImage generated above can be used. Use the following commands in the U-Boot control interface to download uImage and start it:
tftp 0x32000000 uImage 或 nfs 0x30000000 192.168.10.109:/work/nfs_root/uImage
bootm 0x32000000
  • But for the S3C2410 development board, use the same command to start uImage, and after printing the following information (note that the information is printed when the kernel's misc.c file is decompressed), a lot of garbled characters appear, as shown below:
Start kernel........
Uncompressing Linux..................................done
,booting the kernel

Therefore, Linux 2.6.22.6 does not support the S3C2440 development board used in this book. Some modifications are needed. As for which files to modify, you need to understand the kernel's startup code.

The kernel starts the function call process of the second stage (take the S3C2440 development board as an example). The functions with the same indentation indicate that they are called in the same function:

start_kernel ->
	setup_arch ->
		setup_processor
		setup_machine
		...
		parse_tags
		...
		parse_cmdline
		paging_init ->
			devicemaps_init ->
				mdesc->map_io() ->
					s3c24xx_init_io
					s3c24xx_init_clocks
					s3c24xx_init_uarts
		...
		console_init ->
			s3c24xx_serial_initconsole
				register_console(&s3c24xx_serial_console)
				...

Modify the kernel

  • Make the following changes in arch/arm/mach-s3c2440/mach-smdk2440.c:
//修改前
s3c24xx_init_clocks(16934400);

//修改后
s3c24xx_init_clocks(12000000);

  • Then execute make uImage to generate uImage. For S3C2410 and S3CC2440 development boards, the uImage generated above can be used.
    Put uImage in the tftp server directory, or in the /work/nfs_root directory in Linux, and then use the following commands in the U-Boot control interface to download uImage and start it.
tftp 0x32000000 uImage 或 nfs 0x30000000 192.168.10.109:/work/nfs_root/uImage
bootm 0x32000000
  • You can see the boot information of the kernel, and finally the panic information appears (this requires modifying the mtd partition and adding support for the yaffs file system)

Modify MTD partition

MTD (Memory Technology Device), or memory technology device, is a device layer abstracted from ROM, NOR Flash, NAND Flash and other storage devices in LInux. It provides a unified access interface: read, write, erase, etc.; shield The operation of the underlying hardware and the difference between various storage devices are explained. Thanks to the role of the MTD device, it is very simple to repartition the NAND Flash.

The recognition process of the device by the driver

When the driver recognizes the device, there are the following two methods:
(1) The driver itself has device information, such as start address, interrupt number, etc.; when the driver is loaded, the device can be identified based on these information
(2) Driver There is no device information, but the kernel has (or later) determined a lot of device information according to other methods; when loading the driver, compare the driver with these devices one by one to determine whether the two match (mach). If the driver matches a device, the device can be operated by the driver.
The second method is often used in the kernel to identify the device, which can centrally manage the device in one file. When the configuration of the development board is changed, it is easy to modify the code.
In the kernel file include/linux/platform_device.h , two data are defined Structure to represent these devices and drivers: The platform_device structure is used to describe the name, ID, and resources occupied by the device (such as memory address/size, interrupt number), etc.; the platform_driver structure is used to describe various operating functions, such as enumeration functions , Remove the device function, the name of the driver, etc.
After the kernel is started, first construct a linked list to organize the platform_device structure describing the device to get a list of devices; when loading the platform_driver structure of a driver program , use some matching functions to check whether the driver can support these devices, common checks The method is simple: compare the name of the driver and the device.

Modify MTD partition

To change the partition, modify the smdk_default_nand_part structure in the arch/arm/plat-s3c24xx/common-smdk.c file. The NAND Flash is divided into 3 partitions. The first 2MB is used to store the kernel, the next 8MB is used to store the JFFS2 file system, and the rest is used to store the YAFFS file system.

static struct mtd_partition smdk_default_nand_part[] = {
    
    
    [0] = {
    
    
        .name   = "kernel",
        .size   = SZ_2M,
        .offset = 0,
    },  
    [1] = {
    
     
        .name   = "jffs2",
        .offset = MTDPART_OFS_APPEND,
        .size   = SZ_8M,
    },  
    [2] = {
    
     
        .name   = "yaffs",
        .offset = MTDPART_OFS_APPEND,
        .size   = MTDPART_SIZ_FULL,
    },  
};

Among them, MTDPART_OFS_APPEND indicates that the current partition is immediately following the previous partition, and MTDPART_SIZ_FULL indicates that the size of the current partition is the remaining Flash space.
Then execute make uImage to regenerate the kernel

Migrate YAFFS file system

YAFFS (yet another flash file system) is an embedded system similar to scripts in JFFS/JFFS2, specially designed for NAND Flash, suitable for large-capacity storage devices.

There are two steps to transplant yaffs:

  • Add the yaffs2 code to the kernel.
    This can be patched to the kernel through the script file patch-ker.sh in the yaffs2 directory
  • Configure and compile the kernel

Finally execute make uImage to compile the kernel

Guess you like

Origin blog.csdn.net/qq_41782149/article/details/103520415