Reread Booting ARM Linux

Reread Bootring ARM Linux

This time, I will reread Bootring ARM Linux in order to re-recognize what is happening in the boot process of ARM Linux.

(Addition) Originally, it is a part of the Linux Kernel source code, so it will be treated as GPLv2 (recognition).

https://www.kernel.org/doc/html/latest/index.html

Licensing documentation

The following describes the license of the Linux kernel source code (GPLv2), how to properly mark the license of individual files in the source tree, as well as links to the full license text.

https://www.kernel.org/doc/html/latest/process/license-rules.html#kernel-licensing

Let's read it.

https://www.kernel.org/doc/html/latest/arm/booting.html#

In order to boot ARM Linux, you require a boot loader, which is a small program that runs before the main kernel. The boot loader is expected to initialise various devices, and eventually call the Linux kernel, passing information to the kernel.

A boot loader is required to boot ARM Linux. The boot loader is a small program that runs before booting the main kernel. The boot loader will initialize various devices and eventually communicate to the Kernel to call the Linux kernel.

Essentially, the boot loader should provide (as a minimum) the following: 1.Setup and initialise the RAM. 2.Initialise one serial port. 3.Detect the machine type. 4.Setup the kernel tagged list. 5.Load initramfs. 6.Call the kernel image.

In essence, the boot loder does the following (as a minimum configuration):

  1. RAM setup and initialization

  2. Initialize one serial port.

  3. Identification of machine type

  4. Setting up the kernel tagged list

  5. Invite initramfs

  6. Call kernel image.

  7. Setup and initialise RAM

Existing boot loaders: MANDATORY (required) New boot loaders: MANDATORY (required)

The boot loader is expected to find and initialise all RAM that the kernel will use for volatile data storage in the system. It performs this in a machine dependent manner. (It may use internal algorithms to automatically locate and size all RAM, or it may use knowledge of the RAM in the machine, or any other method the boot loader designer sees fit.)

The boot loader will detect and initialize all the RAM that the kernel uses as temporary data storage in the system. This is a machine-dependent approach. (Perhaps it will automatically use the location and capacity of all RAM, knowledge of RAM on the machine, or any other internal algorithm that fits the boot loader designer).

  1. Initialise one serial port

Existing boot loaders: OPTIONAL, RECOMMENDED (optional and recommended) New boot loaders: OPTIONAL, RECOMMENDED (optional and recommended)

The boot loader should initialise and enable one serial port on the target. This allows the kernel serial driver to automatically detect which serial port it should use for the kernel console (generally used for debugging purposes, or communication with the target.)

The boot loader should initialize and enable one serial port on target. This is used by the kernel serial driver to automatically detect the serial port used by the kernel console (generally used for debugging purposes or for communication with the target).

As an alternative, the boot loader can pass the relevant ‘console=’ option to the kernel via the tagged lists specifying the port, and serial format options as described in

Alternatively, the boot loader may notify the kernel of the relevant "console =" option via a tagged list on the port. Details of the serial format option are below.

Documentation/admin-guide/kernel-parameters.rst.

  1. Detect the machine type

Existing boot loaders: OPTIONAL New boot loaders: MANDATORY except for DT-only platforms (probably required for DT-only platfrom)

The boot loader should detect the machine type its running on by some method. Whether this is a hard coded value or some algorithm that looks at the connected hardware is beyond the scope of this document. The boot loader must ultimately be able to provide a MACH_TYPE_xxx value to the kernel. (see linux/arch/arm/tools/mach-types). This should be passed to the kernel in register r1.

The boot loader should detect the machine type that is operating by some means. Using hard-coded values, or reading the connected hardware and using some algorithm, etc., is outside the scope of this document. The boot loader should eventually be able to notify the kernel of the MACH_TYPE_xxx value (see linux / arch / arm / tools / mach-types). This is notified to the kernel via register r1.

For DT-only platforms, the machine type will be determined by device tree. set the machine type to all ones (~0). This is not strictly necessary, but assures that it will not match any existing types.

In DT-only plaftorm, the machine type is used to determine the device tree. The machine type is set to all 1s (~ 0). This is not strictly necessary, but it guarantees that it will not match existing types.

  1. Setup boot data Existing boot loaders: OPTIONAL, HIGHLY RECOMMENDED (optional but highly recommended) New boot loaders: MANDATORY (required)

The boot loader must provide either a tagged list or a dtb image for passing configuration data to the kernel. The physical address of the boot data is passed to the kernel in register r2.

The boot loader must provide either a tagged list or a dtb image as configuration data for the kernel. The physical address of boot data is communicated to the kernel via register r2.

4a. Setup the kernel tagged list

The boot loader must create and initialise the kernel tagged list. A valid tagged list starts with ATAG_CORE and ends with ATAG_NONE. The ATAG_CORE tag may or may not be empty. An empty ATAG_CORE tag has the size field set to ‘2’ (0x00000002). The ATAG_NONE must set the size field to zero.

The boot loader must generate and initialize a kernel tagged list. A valid tagged list ends at ATAG_NONE via ATAG_CORE. ATAG_CORE tag may or may not be. An empty ATAG_CORE tag is set with a size field of '2' (0x00000002). ATAG_NONE must have size filed 0.

Any number of tags can be placed in the list. It is undefined whether a repeated tag appends to the information carried by the previous tag, or whether it replaces the information in its entirety; some tags behave as the former, others the latter.

Some numbers in tags can be stored in list. When a tag is repeated, it is undefined whether it will be added to the information viewed by the previous tag or replace the entire information. Some tags act as the former, while others act as the latter.

The boot loader must pass at a minimum the size and location of the system memory, and root filesystem location. Therefore, the minimum tagged list should look:

The boot loader must at least convey information about the size and location of the system memory and the location of the root filesystem. The smallest tagged list is as follows.

              +-----------+
base ->       | ATAG_CORE |  |
              +-----------+  |
              | ATAG_MEM  |  | increasing address
              +-----------+  |
              | ATAG_NONE |  |
              +-----------+  v

The tagged list should be stored in system RAM. The tagged list is kept in system RAM.

The tagged list must be placed in a region of memory where neither the kernel decompressor nor initrd ‘bootp’ program will overwrite it. The recommended placement is in the first 16KiB of RAM.

The tagged list must be placed in a memory area that does not overwrite the "bootp" prgoram of the kernel decompressor or initrd. The recommended location is the first 16 KiB of memory.

4b. Setup the device tree

The boot loader must load a device tree image (dtb) into system ram at a 64bit aligned address and initialize it with the boot data. The dtb format is documented in Documentation/devicetree/booting-without-of.txt. The kernel will look for the dtb magic value of 0xd00dfeed at the dtb physical address to determine if a dtb has been passed instead of a tagged list.

The boot loader must load the device tree image (dtb) into the 64-bit alignment address on the system RAM and initialize the boot data. The drb format is documented in Documentation / devicetree / booting-without-of.txt. The kernel uses dtb instead of tagged list by finding dtb magic value 0xd00dfeed from the drb physical address.

The boot loader must pass at a minimum the size and location of the system memory, and the root filesystem location. The dtb must be placed in a region of memory where the kernel decompressor will not overwrite it, while remaining within the region which will be covered by the kernel’s low-memory mapping.

The boot loader conveys minimal information such as the size and location of system memory and the location of the root filesystem. dtb must be placed on a memory area that will not be overwritten by the kernel decompressor. And it should be within the area covered by the kernel low memory mapping u.

A safe location is just above the 128MiB boundary from start of RAM.

The area up to the first 128 Mib boundary of RAM is a safe position.

  1. Load initramfs.

Existing boot loaders: OPTIONAL New boot loaders: OPTIONAL

If an initramfs is in use then, as with the dtb, it must be placed in a region of memory where the kernel decompressor will not overwrite it while also with the region which will be covered by the kernel’s low-memory mapping.

When using initramfs with dtb, it must be installed on a memory area that the kernel de compressor does not overwrite. And it should be within the area covered by the kernel low memory mapping u.

A safe location is just above the device tree blob which itself will be loaded just above the 128MiB boundary from the start of RAM as recommended above.

The safe place is just above the device tree. The device tree blob is loaded just above the 128MiB area from the beginning of RAM, as recommended above.

  1. Calling the kernel image

Existing boot loaders: MANDATORY (required) New boot loaders: MANDATORY (required)

There are two options for calling the kernel zImage. If the zImage is stored in flash, and is linked correctly to be run from flash, then it is legal for the boot loader to call the zImage in flash directly.

There are two ways to call kernel zImage. If the zImage is kept in Flash and it is properly linked to work from flash, the boot loader can call zImage directly from within flash.

The zImage may also be placed in system RAM and called there. The kernel should be placed in the first 128MiB of RAM. It is recommended that it is loaded above 32MiB in order to avoid the need to relocate prior to decompression, which will make the boot process slightly faster.

zImage is also located on system RAM and can be called from there. The kernel should be located at the beginning of RAM 128MiB. And it is recommended to load it beyond 32MiB so that it does not need to be relocated after deployment. This makes the boot process slightly faster.

When booting a raw (non-zImage) kernel the constraints are tighter. In this case the kernel must be loaded at an offset into system equal to TEXT_OFFSET - PAGE_OFFSET.

The restrictions are even more stringent when booting the ram (non-zImage) kernel. In this case, the kernel must load the kernel at an offset equal to TEXT_OFFSET --PAGE_OFFSET.

In any case, the following conditions must be met:

In either case, the following conditions must be met.

· Quiesce all DMA capable devices so that memory does not get corrupted by bogus network packets or disk data. This will save you many hours of debug.

All DMA capable devices must be stopped so that they do not get network packets or disk data. This will save you a lot of time for debugging,

・ CPU register settings r0 = 0, r1 = machine type number discovered in (3) above. r2 = physical address of tagged list in system RAM, or physical address of device tree block (dtb) in system RAM CPU mode

CPU register settings. r0 = 0, r1 = machine type num mentioned in 3 above. r2 = physical address of tagged list in system RAM or device tree block (dtb) in system RAM CPU mode.

All forms of interrupts must be disabled (IRQs and FIQs)

All interrupts (IRQ / FIQ) must be disabled.

For CPUs which do not include the ARM virtualization extensions, the CPU must be in SVC mode. (A special exception exists for Angel)

If the CPU does not include virtualization extensions, then the CPU is in SVC mode (Angel has a special exception)

CPUs which include support for the virtualization extensions can be entered in HYP mode in order to enable the kernel to make full use of these extensions. This is the recommended boot method for such CPUs, unless the virtualisations are already in use by a pre-installed hypervisor.

If the CPU contains virtualized extensions, enter HYP mode to make these extensions available to the kernel at full. This is the recommended boot method for such CPUs, unless virtualization is already in use by a pre-installed hypervisor.

If the kernel is not entered in HYP mode for any reason, it must be entered in SVC mode.

If the kernel does not enter HYP mode for any reason, it must enter SVC mode.

・ Caches, MMUs The MMU must be off. Instruction cache may be on or off. Data cache must be off.

・ Cache, MMU The MMU must be OFF. The instruction cache may be On or Off. The data cache must be Off.

If the kernel is entered in HYP mode, the above requirements apply to the HYP mode configuration in addition to the ordinary PL1 (privileged kernel modes) configuration. In addition, all traps into the hypervisor must be disabled, and PL1 access must be granted for all peripherals and CPU resources for which this is architecturally possible.

If the kernel boots in HYP mode, the above requirements apply to HYP mode configurations in addition to normal PL1 (privileged kernel mode). In addition, disabling all traps to the hypervisor, PL1 must be accessible to all peripherals and CPU Resources for which the architecture is available.

Except for entering in HYP mode, the system configuration should be such that a kernel which does not include support for the virtualization extensions can boot correctly without extra help.

Except when entering HYP mode, the system configuration must allow kernels that do not include virtualization extension support to boot properly without special assistance.

・ The boot loader is expected to call the kernel image by jumping directly to the first instruction of the kernel image.

The boot loader calls the kernel image by jumping directly to the first instruction in the kernel image.

・ On CPUs supporting the ARM instruction set, the entry must be made in ARM state, even for a Thumb-2 kernel.

Any CPU that supports the ARM instruction set, even with a Thumb-2 kernel, may enter in the ARM state.

On CPUs supporting only the Thumb instruction set such as Cortex-M class CPUs, the entry must be made in Thumb state.

CPUs like the Cortex-M class that only support the Thumb instruction set must be entered in the Thumb state.

Recommended Posts

Reread Booting ARM Linux
Linux
Run docker-compose on Amazon Linux2 on ARM64
Run Linux on ARM architecture with QEMU