Flashing nand with sdcard data from kernel - linux-kernel

I have used following steps to flash nand on my board from u-boot.
Booted the baord from sdcard and stopped at U-boot.
Loaded kernel from sdcard to RAM
#mmc read ${loadaddr} 0x800 0x1800
Erased nand flash using nand erase command.
#nand erase offset size
Copied kernel from RAM to nand.
#nand write ${loadaddr} offset size
I want to do the same steps in Kernel, can you guide me how to copy data from sdcard to RAM in kernel(looking for alternate command for u-boot "mmc read"). I am using IMX53 based custom board.

It is not recommended to do that as it may block the kernel, it is recommended to do it in uboot itself or you should write your code in proper manner concerned with locking and sync.
For doing it you can create a function for by using nand & mmc driver function. NAND read/write MMC read/write can be by calling their respective read write Using NAND funtions from kernel and MMC Kernel API reference respectively.
Then call your function inside file /init/main.c and function __init start_kernel(void) here. And your function you can declare in the same file somewhere at last.

I could able to do with dd command.
#dd if=/dev/mmcblk0 of=/dev/mtd1 bs=1M skip=1 count=3

Related

why is load address of kernel, ramdisk important in booting?

I am dealing with android boot.img which is a combination of compressed kernel, ramdisk, and dtb. I see from the serial console log from uboot about the booting process and here's the part that triggers my curiosity
CPU: Freescale i.MX6Q rev1.2 at 792 MHz
CPU: Temperature 27 C
Reset cause: POR
Board: MX6-SabreSD
I2C: ready
DRAM: 1 GiB
PMIC: PFUZE100 ID=0x10
MMC: FSL_SDHC: 0, FSL_SDHC: 1, FSL_SDHC: 2
No panel detected: default to Hannstar-XGA
Display: Hannstar-XGA (1024x768)
In: serial
Out: serial
Err: serial
check_and_clean: reg 0, flag_set 0
Fastboot: Normal
flash target is MMC:1
Net: FEC [PRIME]
Normal Boot
Hit any key to stop autoboot: 3 2 1 0
boota mmc1
kernel # 14008000 (7272352)
ramdisk # 15000000 (869937)
fdt # 14f00000 (44072)
## Booting Android Image at 0x12000000 ...
Kernel load addr 0x14008000 size 7102 KiB
Kernel command line: console=ttymxc0,115200 init=/init video=mxcfb0:dev=hdmi,1920x1080M#60,bpp=32 video=mxcfb1:off video=mxcfb:off video=mxcfb3:off vmalloc=256M androidboot.console=ttymxc0 consolebalank=0 androidboot.hardware=freescale cma=384M
## Flattened Device Tree blob at 14f00000
Booting using the fdt blob at 0x14f00000
Loading Kernel Image ... OK
Using Device Tree in place at 14f00000, end 14f0dc27
switch to ldo_bypass mode!
Starting kernel ...
The kernel's address is 14008000, ramdisk 15000000, fdt 14f00000.
I have found out that these values are saved in the boot.img header and when I manually mess with this values, the image will not boot even though the actual contents are not modified.
Why is this address so critical? Why does it have to be these values? why not other values?
One of my own guess is:
these load address values are hardcoded inside the kernel so if I change it in the boot.img header it will cause side-effects. To elaborate my own theory, loading the kernel to the 'modified' load addr won't be a problem. But when actually executing the lines, it will cause severe problems because these codes are fixed to work with the proper 'load addr'.
Is my theory wrong? If so, I'd be grateful if you could correct me.
After the U-boot finished, it needs to handover the further execution to kernel so that kernel takes care for all further processes. Plus Kernel have some set of routines which are essential to initialize the board.
These set of routines have a entry point start_kernel(). Before this some other routines are also called to execute start_kernel. That can be identified by this linker script and this init.S.
To maintain execution in this procedure kernel need to be started from a particular address, moreover its data segments and other memories are also attached with that so to load and run all these in a proper manner, exact memory location need to be provided.
With this kernel needs the device tree blob for probing the devices attached to it and the rootfs to bring up the user space, here to load the device tree and rootfs exact offsets are needed so that any data should not be missed or corrupted. Every single byte is important for all these execution.
So to safely bootup all these values are being stored in bootloader's configuration.

Linux Kernel Booting Approach Pre built rootfs

I am learning the linux kernel booting process and trying to install linux on my beagleboard xM. I came across two approach both using the SD card.
1. Have the MLO, initrd, uboot.bin and uImage in one partition.
2. Have the MLO, uboot.bin and uImage in one partition and a pre-built rootfs (Angstrom) in 2nd partition.
In the first approach how is the initrd transformed into a complete file system on the 2nd partition. And what happens internally when uboot extracts the kernel from uImage and paste it on the 2nd partition. which directories would get modified of the init rootfs. How the init process of the kernel is called.
In general, the booting sequence in the Beagleboard-XM is something like this :
Firmware -> MLO -> uboot.bin -> uImage -> initrd(optional) -> rootfs
The initrd itself is a simple RAM based file system. It is generally used to mount the actual file system. Some of the modules which are required to mount the rootfs are bundled up into the initrd. Once the rootfs is mounted, the initramfs is cleaned up. If the features that are required to mount the rootfs is built into the kernel (uImage) itself, then there is no need of initrd. As I said earlier, initrd is a simple RAM based file system. That means if you use this as your filesystem, anything you write onto it will not be preserved. A few embedded applications actually use this as their rootfs.
Now answering to your question,
How is the initrd transformed into a complete file system on the 2nd partition?
Initially u-boot loads the kernel(uImage), initrd onto RAM and pass the appropriate the command line arguments to the kernel. Once the u-boot transfers the control over to the kernel, it first initializes the drivers and other modules and finally looks for initrd. The initrd is generally put as a cpio image. The kernel then uncompresses it and looks for 'init'. The init processes few things and then mounts the rootfs. There is no such thing as 2nd partition when it comes to initrd. It resides on the RAM.
What happens internally when uboot extracts the kernel from uImage and paste it on the 2nd partition?
Again, there is no such things as 2nd partition when it comes to uImage. uImage is a format which is understood by u-boot. The u-boot first loads the uImage onto the RAM and before actually passing the control over to the kernel, it extracts the contents from uImage, moves the binary to a predefined location in the RAM and then passes the control over to the kernel. Similar to initrd, the kernel also resides on the RAM itself.
Which directories would get modified of the init rootfs?
No directories gets modifies. But yes, a few of them are mounted, like procfs, sysfs, etc.
How the init process of the kernel is called?
Please refer to the kernel_init() function under init/main.c to see how the kernel executes init (refer http://lxr.free-electrons.com/source/init/main.c#L871).
I am attaching a simple code snippet from it :
if (!try_to_run_init_process("/sbin/init") ||
!try_to_run_init_process("/etc/init") ||
!try_to_run_init_process("/bin/init") ||
!try_to_run_init_process("/bin/sh"))
return 0;
panic("No working init found. Try passing init= option to kernel. "
"See Linux Documentation/init.txt for guidance.");
Therefore, the kernel searches in these default paths for the init binary. If it is not found, the kernel panics!
Hope this helps.

How to invalidate cache in kernel driver?

I have an output buffer in my kernel driver. And that share with my hardware, which uses it for output.
When I got an interrupt, the kernel driver will copy the data from the output buffer to user space buffer.
How can I invalidate cache after my kernel driver copy the output buffer?
I used dmac_inv_range(). Pass the beginning and the end of the area you want to invalidate.

The using of address ZTEXTADDR in Linux booting for ARM

What is the role of ZTEXTADDR in Linux kernel ?
From lxr.linux.no, it's an address in RAM that holds address of zImage as sequence below?
A.
uImage (DataFlash/NAND) ---load_to_RAM--->
uImage (# boot_addr) ---decompress_uImage-->
zImage (# ZTEXTADDR) --- decompress_zImage--->
uncompressed image (# ZRELADDR).
or just:
B.
uImage (DataFlash/NAND) ---load_to_RAM--->
uImage (# boot_addr) ---decompress_uImage-->
uncompressed image (# ZRELADDR)
no using ZTEXTADDR in new kernel version for booting process ?
The Linux ARM decompression boot loader is capable of relocating itself when running from RAM. The relocation portion is PC-relative and so it can be loaded at any address. However, if your main image starts from FLASH/ROM, the code can not be relocated; while moving an image in RAM is a simple memmove(), it is much more involved for NOR flash and can be impossible for ROM.
In this case, a compressed boot linker script is used with the ZTEXTADDR as the location of the decompression code. In your diagram, you have a u-boot, which will load the uImage. There is no reason to execute this directly from Flash/ROM. u-boot can copy the image to RAM and there is no need for the ZTEXTADDR value and it should be left as zero.
If your image boots directly from Flash/ROM, without a boot loader then ZTEXTADDR is useful,
zImage (in flash) --> decompress vmlinux.bin to RAM --> run kernel
The zImage may need to be annotated with some chip setup for this to work and would need ATAGS or device trees linked. For this reason, there are many machine variants in boot/compressed; This is not maintainable and these type of files are discouraged. Typically another bootloader loads the image to RAM and the zImage can move itself to whatever destination it needs; I think that is your situation and you should set ZTEXTADDR to zero and forget about it.

U-Boot hangs while loading kernel?

I am working on Freescale board imx50evk. I have built the uboot.bin and uImage using LTIB (linux target image builder). At the U-Boot prompt I enter the bootm addr command, and then it hangs after showing the message "Loading Kernel..."
> MX50_RDP U-Boot > boot
MMC read: dev # 0, block # 2048, count 6290 partition # 0 ...
6290 blocks read: OK
## Booting kernel from Legacy Image at 70800000 ...
Image Name: Linux-2.6.35.8
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1323688 Bytes = 1.3 MB
Load Address: a0008000
Entry Point: a0008000
Verifying Checksum ... OK
Loading Kernel Image ...
You need to verify that your board really has RAM at 0xa0008000, which is the kernel "load address". U-Boot is probably trying to copy the image to that region of memory when it appears to hang.
[By your comment, I'll assume that you have verified that main memory does not exist at physical address 0xAXXXXXXX.]
The uImage file that you are using was made from the zImage file using the mkimage utility.
You probably have to manually edit the line that looks like
zreladdr-y := 0xa0008000
in arch/arm/mach-XXX/Makefile.boot for your board. The convention is that this address should be the base of physical RAM plus an offset of 0x8000 (32K). Then adjust the other values in the file. Delete the zImage file and perform another make for the kernel.
While building 3.20 development kernels for rockchip's rk3288 I found using LZO image compression made the device hang at 'Starting the kernel.' I assume it's because of a version miss-match between the build hosts LZO and the deployed decompression code, so it could probably happen with any of the compression algorithms. In my case switch to gzip fixed it.
This is only my assumption for why changing the compression algorithm gave a bootable kernel. Please correct me if I'm wrong.

Resources