How to add new device in uboot? - linux-kernel

I want to access the different peripherals of i-MX6 at uboot level but I don't know how to do that?
How to add support for new devices in u-boot?
what are the differences between drivers present in u boot level and kernel level?

The five (4) boot phases.
1.ROM loads x-load (MLO)
2.X-load loads u-boot --> Primary boot-loader
3.U-boot reads commands/Load kernel --> Secondary Boot-Loader
4.Kernel reads root file system.
x-loader (Primary Boot-Loader) :
The x-loader configures the pin muxing, clocks, DDR, and serial console, so that it can access and load the second stage bootloader (u-boot) into the DDR
U-Boot (Secondary Boot-Loader) :
The u-boot can perform CPU dependent and board dependent initialization and configuration not done in the x-loader. The u-boot also includes fastboot functionality for partitioning and flashing the eMMC. The u-boot runs on the Master CPU (CPU ID 0), which is responsible for the initialization and booting; at the same time, the Slave CPU (CPU ID 1) is held in the “wait for event” state.
U-Boot is kind of firmware. It'll basically initialize basic functionality. Like Display, CPU0, FastBoot functionality, Create a temporary file system for loading a kernel and Loading Kernel.
Kernel Driver :
A device driver is a program that controls a particular type of device that is attached to your computer. There are device drivers for printers, displays,Touch, CD-ROM readers, diskette drives, and so on.
U-Boot is mainly for loading a Operating System (Kernel). Device Driver is part of kernel for controlling a device. you want to accesses your device in u-boot loader then you will have to initialize all need hardware for your device like memory an all.

Related

How is the instruction memory initialized?

In my book, in the chapter where they create the CPU (chapter 7), they already assume that the instruction memory contains the instructions in machine code.
In an earlier chapter (chapter 6) this is written about start-up:
On start-up, the processor jumps to the reset vector and begins
execution boot loader code in supervisor mode. The boot loader
typically configures the memory system, initializes the stack pointer,
and reads the OS from disk; then it begins a much longer boot process
in the OS. The OS eventually will load a program, change to
unprivileged user mode, and jump to the start of the program.
But from what I understand the reset vector and the boot loader code must be in memory? Is this correct? Has my book skipped a part before the CPU jumps to the reset vector, and forgot about
how the reset vector and bootloader are loaded into memory? How does the CPU get them into memory?
All CPUs have a fixed start address. This is set in hardware (maybe you can configure it through jumpers but that's it, because the CPU has to start somewhere).
The first instructions are again set in hardware, at such fixed address, usually through a hard coded memory (like a flash). There likely is a piece of hardware that translates accesses to an address-based location to flash (NAND memory), so that means that the flash, even if it's not part of the CPU, is memory mapped.
Some processors do a memory remap, meaning that you will have those addresses accessible for other things, as you likely don't need the first stage bootloader anymore.
We can explore further by taking as an example the STM32 boot process:
Configurable boot mode though physical pins and jumpers:
This means that the CPU can start fetching instructions at startup from different locations, defined by those pins.
Factory bootloader:
The bootloader is stored in the internal boot ROM (system memory part of the flash) of any STM32 device, and is programmed by ST during
production. Its main task is to download the application program to the internal flash memory through one of the available serial peripherals, such as USART, CAN, USB, I2C, or SPI.
So this means that if the factory bootloader is selected, the CPU will start execute a program that then, by means of the selected communication protocol (USART, CAN etc..) can fetch a program from another device. This is useful if you have another processor needed to program your device once already mounted on the PCB.
Another option - Write directly to the internal flash
Another option is to select the internal flash. Since this is a persistent memory it can be programmed externally and when the CPU will start it will find, at 0x8000000, the first instruction to execute. The last section of the page that I linked explain the boot process.

Difference between Character Device, Platform Driver and Kernel Module

I am a newbie to Linux Kernel device driver codes.
One question up on the other: which is the difference between:
Character Device
Platform Driver
Kernel Module
I am writing this question because, within the same code I am examining, there are three section: one for each.
Platform Device Driver:
A platform device driver is generally written for on-chip components/devices and on-chip/off-chip unspeakable/un-discoverable devices.
If there is a device on-chip/off-chip, which doesn't have a self-identifying capability, like say i2x devices, GPIO line based, or in-circuit (on-chip) timers, etc. Then such devices need to be identified by the drivers because the devices don't have self-ID, or capability to identify themselves. This generally happens with bus lines and on-chip components.
Here is detailed explanation.
Example platform Devices: i2c devices, kernel/Documentation/i2c/instantiating-devices states:
Basically, all device drivers can be categorized into character, or block; based on the data transaction size.
Though there are many sub-classifications like network devices drivers and X device drivers, they too can be brought into devices, which carry data transactions (operations) in terms of few bytes that undergo tr
Typically, a platform device driver can fit into character device driver section, as they generally involve on-chip operations, for initialization and to transfer a few bytes, whenever needed, but not in terms of blocks (KB, MB, GB) of data.
Kernel Module?
Now, a driver can be either compiled (to be integrated) into kernel image (zImage/bzImage/...) OR can be compiled (off-the kernel) to be optionally invokable modular driver, which is not part of kernel image, but is part of filesystem as a .ko (kernel object) file (find /lib/modules/`uname -r`/ -name "*.ko"), that stays off the kernel image, but can be inserted (using modprobe/insmod) or removed (using rmmod/modprobe -r) as necessary.
On the other hand, a built-in driver can't be removed dynamically, even if we don't need it momentarily. A built-in driver would remain in the kernel and hence on RAM, as long as the system is running, even if the respective device is "not found"/"not necessary/"shutdown"), just wasting memory space (on RAM).
The Module (or modular driver), would only step-in, when necessary, from secondary storage to RAM, and can be removed if the device is removed or not-in-action. This saves RAM and helps dynamic allocation of resources.

How does U-Boot communicate with Linux kernel?

I'm reading the book and it tells that:
After U-Boot loads Linux kernel, the kernel will claim all the resources of U-Boot
What does this mean? Does it mean that all data structures that allocated in U-Boot will be discarded?
For example: during U-Boot, PCIE and Network Device will be initialized.
After booting Linux kernel, will the PCIE and Network Device data structure be discarded? Will the Linux kernel do PCIE and NEtwork initialize again? Or U-Boot will transfer some data to kernel?
It depends on your CPU architecture how the communication happens, but it is usually via a special place in RAM, flash or the filesystem. No data structures are transferred, they would be meaningless to the kernel and the memory space will be different between the two. Uboot generally passes boot parameters like what type of hardware is present, what memory to use for something, or which type of mode to use for a specific driver. So yes, the kernel will re-initialize the hardware. The exception may be some of the low level CPU specifics which the kernel may expect uboot or a BIOS to have setup already.
Depending on your architecture, there may be different mechanism for the u-boot to communicate with the Linux kernel.
Actually there may be some structures defined by u-boot which are transferred to and used by the kernel using ATAGS. The address in which these structure are passed is stored in r2 register on ARM. They convey information such as available RAM size and location, kernel command line, ...
Note that on some architectures (like ARM again) we have support for device-tree which intends for defining the hardware in which the kernel is going to be run as well as kernel command line, memory and other thins. Such description is usually created during kernel compile time, loaded into the memory by the u-boot and in case of ARM architecture, its address is transferred through r2 register.
The interesting thing about this (regarding your question) is that u-boot can change this device-tree structure before passing it to the kernel through device tree overlay mechanism. So this is a (relatively) new way of u-boot/kernel communication. Note that device-tree is not supported on some architectures.
And at the end, yes, the hardware is reinitialized by the kernel even in they have already initialized by the u-boot except for memory controller and some other very low level initialization, AFAIK.

Embedded Linux Newbie Questions

So I am on the quest of learning embedded Linux and have a few questions that I cannot seem to find an answer for.
1) Does the kernel depend on the dtb/dts files when compiling? I thought that the kernel only needs to know the chip architecture (i.e. arm) and the dtb file is loaded by the boot loader (uBoot) so therefore the kernel only needs to load its drivers which are configured by the dtb file.
2) Mixing and matching: I'm under the impression that I can mix and match any combination of boot loader, dtb, kernel, rootfs, and modules given the following
kernel: must know which chip it is compiled for
dtb: must know the board details and chip, i.e. how much ram, configure a GPIO for SPI
boot loader: must know the chip and uEnv.txt must have params for the kernel and dtb location
rootfs: completely independent
modules: must be compiled with the specific version of kernel
3) Drivers: If I want to load a SPI driver do I need anything specific or will the kernel know how to operate this because the dtb file setup the required registers?
4) Modules: Are these just dependent on the kernel or do they need to know something about the chip and board (when I say chip what I mean is do they have to know more than a simple arm or x86 architecture)?
Thank you in advance, I know these are some basic questions but any help is appreciated.
1) Does the kernel depend on the dtb/dts files when compiling? I thought that the kernel only needs to know the chip architecture (i.e. arm) and the dtb file is loaded by the boot loader (uBoot [sic]) so therefore the kernel only needs to load its drivers which are configured by the dtb file.
The Linux kernel is compiled without any dependency on the Device Tree.
The compilation of the kernel does depend on the chip architecture, but which code modules that are compiled depends on the board configuration(s) and feature selection.
BTW it's U-Boot for Universal Boot, not microBoot.
2) Mixing and matching: I'm under the impression that I can mix and match any combination of boot loader, dtb, kernel, rootfs, and modules given the following
kernel: must know which chip it is compiled for
dtb: must know the board details and chip, i.e. how much ram, configure a GPIO for SPI
boot loader: must know the chip and uEnv.txt must have params for the kernel and dtb location
rootfs: completely independent
modules: must be compiled with the specific version of kernel
Essentially correct, but typically one doesn't go overboard in trying to "mix-n-match". There are often optimal or preferred (or at least appropriate) choices.
By "rootfs" I'm assuming you mean type of filesystem for the rootfs, rather some image of a rootfs. (See Addendum below.)
3) Drivers: If I want to load a SPI driver do I need anything specific or
There are two types of "SPI driver", the master and protocol.
The SPI master driver is for the SPI controller chip that serves as the one interface master. This is usually a platform driver and not have a device node in /dev.
For each SPI slave device there must be a protocol driver. This driver will typically have a device node in /dev.
will the kernel know how to operate this because the dtb file setup the required registers?
The Device Tree must specify which driver is for which device and any/all resources allocated/assigned to each device.
The dtb file does not "setup" anything. It's only configuration data; there is no executable code. A device driver, typically during its probe or initialization phase, is responsible for acquiring/allocating its resources.
4) Modules: Are these just dependent on the kernel or do they need to know something about the chip and board?
Your use of "modules" is ambiguous. Source code files are sometimes referred to as "modules". Presumably you really mean loadable kernel modules.
Although most people associate kernel modules (only) with device drivers, other kernel services such as filesystems and network protocol handlers can also be built as modules.
The primary rationale for a kernel module versus static linkage (i.e. built in the kernel) is for runtime configurability (which in turn improves memory efficiency). Optional features, services and drivers can be left out of the kernel that is booted, but can still be loaded later when needed.
Loadable modules are "dependent" on the kernel simply because of linking requirements for proper execution. The degree of "chip and board knowledge" obviously depends on the functionality of the module, just like any other piece of kernel code.
Addendum
when I say rootfs I am referring to a prebuilt rootfs
A kernel image and (prebuilt) rootfs image are not "completely independent".
The executable binaries and the shared libraries in the rootfs image must be compatible with the kernel features. More significantly, since kernel loadable modules are installed in the rootfs and not with the kernel image, and these modules can be strictly tied to a specific build of a kernel version, it makes sense to pair a kernel image with a rootfs image.

Difference between bootloader and bootstrap loader?

how boot loader is different from bootstrap loader. According to me bootstrap loaders are stored in ROM and boot loaders are in hard disk in MBR (please correct me if I am wrong). bootstrap loader is the first program which get executed after startup. Now I am not getting the meaning of these sentences:-
After power on , the bootloader is controlling the board and does not rely on the linux kernel on any way.
And
The bootstrap loader acts as a glue between the bootloader and the linux kernel.
what these mean? And why we require both of them?
Bootstrap Loader
Alternatively referred to as bootstrapping, bootloader, or boot program, a bootstrap loader is a program that resides in the computer's EPROM, ROM, or other non-volatile memory. It is automatically executed by the processor when turning on the computer. (Come from WIKI)
You can think it will turn on immediately after power on, and it's part of the BIOS(BIOS has many other functions such as providing some diagnostic output, and providing a way for the user to configure the hardware)
Pay attention, in some situation Bootstrap Loader can also be called as bootloader or bootstrap...
Bootloader
Bootloader is a piece of code that runs before any operating system is running. Bootloader are used to boot other operating systems, usually each operating system has a set of bootloaders specific for it. (Come from google)
HERE IS THE STEP
0 : Power On!
1 : CPU Power On! CPU try to find something in ROM(Or ERROM)
2 : Find BIOS (or other firmware). Run BIOS
3 : BIOS(bootstrap loader and other functions) run
4 : BIOS try to find something in MBR
5 : Find MBR(512 bytes) there is some useful information of the partition
6 : Copy the MBR content into physical disk 0x7c00 where is the location of the Grub.
7 : Grub(a type of bootloader) use the information of the MBR finds a linux! Prepare to run.
8 : Run your linux!
Many architectures use a bootstrap loader or second-stage loader to load the Linux kernel image into memory. Some bootstrap loaders perform checksum verification of the kernel image, and most perform decompression and relocation of the kernel image.
The difference between a bootloader and a bootstrap loader in this context is simple:
bootloader
The bootloader controls the board upon power-up and does not rely on the Linux kernel in any way.
bootstrap loader
In contrast, the bootstrap loader's primary purpose in life is to act as the glue between a board-level bootloader and the Linux kernel. It is the bootstrap loader's responsibility to provide a proper context for the kernel to run in, as well as perform the necessary steps to decompress and relocate the kernel binary image.
Alternatively referred to as bootstrapping, boot loader, or boot program, a bootstrap loader is a program that resides in the computers EPROM, ROM, or other non-volatile memory that automatically executed by the processor when turning on the computer. The bootstrap loader reads the hard drives boot sector to continue the process of loading the computers operating system. The term boostrap comes from the old phrase "Pull yourself up by your bootstraps." The boot loader has been replaced in computers that have an Extensible Firmware Interface (EFI). The boot loader is now part of the EFI BIOS.
A bootloader, such as U-Boot or RedBoot, takes control of the hardware immediately after turn on. Boostrap loader, on the other hand, is attached to the kernel image to prepare a proper context for running kernel. For example, when compiling the kernel for an ARM architecture, the kernel file is compiled as the piggy.o file, and the boostrap loader files are misc.o, big_endian.o and head.o.

Resources