Jump to content

U-Boot porting

From postmarketOS Wiki
Revision as of 13:23, 7 July 2022 by Jenneron (talk | contribs) (add u-boot table)


Why bother?

Porting u-boot to your phone gives you more control, when booting mainline kernels, namely:

  1. Adjusting boot command line
  2. Dual-boot without hacks
  3. Prevent stock bootloader from kernel / device tree modification

Supported Devices

Device Codename Primary Bootloader Secondary Bootloader Mainline Internal storage SD USB Host USB Peripheral Screen Keyboard Buttons
Acer Chromebook 13 (CB5-311) google-nyan-big Y Y Y Y - N Y -
Apple Mac mini M1 apple-j274ap - Y Y Y - Y Y Y Y -
Apple MacBook Air apple-tonga - Y Y Y - Y Y Y Y -
Apple Tonga tonga-generic - Y Y Y - Y Y Y Y -
Arrow DragonBoard 410c arrow-db410c Y Y Y Y Y Y - Y
Asus Chromebook C201 google-veyron-speedy Y Y Y Y Y P - Y Y -
Asus Chromebook Flip C100 google-veyron-minnie Y N Y Y - Y Y -
Asus Eee Pad Transformer asus-tf101 Y Y Y Y Y Y Y Y N Y
Asus Eee Pad Transformer Prime asus-tf201 Y Y Y Y Y Y Y Y N Y
Asus Transformer Infinity asus-tf700t Y Y Y Y Y Y Y P N Y
Asus Transformer Pad asus-tf300t Y Y Y Y Y Y Y Y N Y
Asus Transformer Pad (TF701T) asus-tf701t P P Y Y Y Y Y Y N Y
Asus Transformer Pad 3G asus-tf300tg Y Y Y Y Y Y Y Y N Y
Asus VivoTab RT asus-tf600t Y - Y Y Y Y Y N N Y
Beelink gt1 (Ultimate) beelink-gt1 Y Y Y Y Y Y Y Y Y
CDI EduGear Chromebook K google-veyron-jerry Y N Y - Y Y -
CTL Chromebook J2 / J4 google-veyron-jerry Y N Y - Y Y -
Digma 1538E 4G digma-ps1150ml Y Y N Y N -
DongshanPi NeZha STU dongshanpi-nezhastu Y - Y Y Y Y N - -
Epik Chromebook ELB1101 google-veyron-jerry Y N Y - Y Y -
Google (ASUS) Nexus 7 (2012) asus-grouper Y N Y Y - N Y Y - Y
Google (ASUS) Nexus 7 (2012) GSM asus-tilapia Y N Y Y - N Y Y - Y
Hisense Chromebook 11 google-veyron-jerry Y N Y - Y Y -
HP Chromebook 14 G3 google-nyan-blaze Y Y N Y N - Y Y -
HTC One X htc-endeavoru Y N Y Y - N Y Y - Y
iNet Tek D70 A33 inet-a33 N Y Y Y -
LG Optimus 4X HD lg-p880 Y P Y Y Y - Y Y - Y
LG Optimus Vu lg-p895 Y P Y Y - - Y Y - Y
MangoPi MQ-Pro mangopi-mq-pro Y - Y - Y Y Y N - -
Mecer Xpression V2 google-veyron-jerry Y N Y - Y Y -
Medion Chromebook S2013 google-veyron-jaq
Microsoft Surface RT microsoft-surface-rt P P Y Y Y Y Y N Y
NComputing Chromebook CX100 / CX110 google-veyron-jerry Y N Y - Y Y -
Nokia N900 nokia-n900 Y Y Y Y - Y Y Y Y
Nvidia Tegra Note 7 nvidia-tegratab P P Y Y Y N Y Y - Y
ODROID HC2 odroid-hc2 Y - Y Y -
Oysters T74ER oysters t74er Y Y N Y Y Y Y
Oysters T84Bi 4G oysters-t84bi-4g Y Y N Y N -
Poin2 Chromebook 11 google-veyron-jerry Y Y Y Y Y Y - Y Y -
Positivo Chromebook CH1190 google-veyron-jerry Y N Y - Y Y -
Qualcomm Snapdragon 410 qcom-msm8916 N P P Y Y N N Y Y Y
Qualcomm Snapdragon 845 qualcomm-sdm845 N Y P Y Y P Y Y Y Y
Radxa Zero radxa-zero Y - Y Y Y Y Y Y Y
Samsung Chromebook google-snow Y Y Y Y Y - Y Y -
Samsung Chromebook 2 11.6" google-peach-pit Y Y Y Y Y - Y Y -
Samsung Chromebook 2 13.3" google-peach-pi Y Y Y Y Y - Y Y -
Samsung Chromebook Plus google-kevin Y Y Y Y Y Y - Y Y N
Samsung Galaxy Ace 2 GT-I8160 samsung-codina N Y Y Y Y Y Y - Y
Samsung Galaxy Amp (SGH-I407) samsung-kyle N Y Y Y Y Y Y - Y
Samsung Galaxy Beam samsung-gavini N Y Y Y Y Y Y - Y
Samsung Galaxy Exhibit (SGH-T599) samsung-codina-tmo N Y Y Y Y Y Y - Y
Samsung Galaxy Grand Prime+ samsung-grandpplte N Y N Y N N - Y
Samsung Galaxy S Advance samsung-janice N Y Y Y Y Y Y - Y
Samsung Galaxy S II samsung-i9100 Y N -
Samsung Galaxy S III samsung-m0 Y - N -
Samsung Galaxy S III Mini samsung-golden N Y Y Y N Y Y Y - Y
Samsung Galaxy S9 (SM-G9600/DS) samsung-starqltechn N Y N - Y
Samsung Galaxy Xcover 2 GT-S7710 samsung-skomer N Y Y Y Y Y Y - Y
VideoNet Chromebook BL10 google-veyron-jerry Y N Y - Y Y -
Xiaomi Mi Pad xiaomi-mocha Y Y Y Y Y N Y P - Y
Xiaomi Redmi Note 12 Pro (4G) xiaomi-sweet_k6a - Y N P N N P Y - Y
Xunlong Orange Pi 3 xunlong-orangepi3 Y - Y Y Y N N -
Xunlong Orange Pi 5 xunlong-orangepi-5
Xunlong Orange Pi PC xunlong-orangepi-pc Y - Y Y -

About

This article will guide you on porting u-boot on your phone. It's possible, even if there is no complete SOC support in uboot tree (only uart driver needed), because stock bootloader initialized hardware for us. First thing to focus on should be getting u-boot shell prompt.

Preparation

  1. Find uboot code
  2. Before starting uboot porting, you should get access to the stock bootloader uart port. Make sure you can see stock bootloader logs.
  3. Search uboot code for a uart driver, compatible with your SOC. It is good, if it support debug(i.e. include debug_uart.h)
  4. Get familiar with you phone RAM map
  5. Some useful links:

- bring up process
- configuration process

Read the following readme files:

  • top README
  • doc/README.kconfig
  • doc/usage/environment.rst

Create basic configuration, building and running

Add board files

Use guide from Free Electrons pdf or video version

Examples

  1. Add exynos7420 espresso board
  2. Add exynos7420 SOC support

Configure

U-boot configuration system comes from linux kernel. Put config options not supposed to be changed by user in /include/configs/.*.h files, in *_defconfig otherwise

Options, you DO NOT need

  • All SPL related options. SPL(Secondary Program Loader) splits u-boot in two parts. You don't need this, since stock bootloader will load whole u-boot image into RAM.
  • CONFIG_BOARD_EARLY_INIT_F

Options, you need

  • CONFIG_SYS_MALLOC_LEN - size of early C runtime environment heap
  • CONFIG_SYS_INIT_SP_ADDR - address of early C runtime environment stack (should be in RAM address space, but NOT at the bottom, because stack is growing DOWN. see u-boot readme memory management section). This option valid, when CONFIG_POSITION_INDEPENDENT=n.
  • CONFIG_SYS_INIT_SP_BSS_OFFSET - when CONFIG_POSITION_INDEPENDENT=y, defines offset to early c runtime stack from bss section from bss section. Default is 512K.
  • CONFIG_SYS_TEXT_BASE - u-boot base address. It's the address in RAM, where u-boot is loaded by stock bootloader. Not obligatory, if you use position independent build with CONFIG_POSITION_INDEPENDENT=y. See instructions below, how to find it.
  • CONFIG_SYS_SDRAM_BASE - start address of the dynamic RAM. Can be found in memory node in linux device tree.
  • CONFIG_DEBUG_UART=y
  • CONFIG_DEBUG_UART_SKIP_INIT=y - make sure to comment _debug_uart_init function code in you serial driver with that option
  • CONFIG_DEBUG_UART_BASE=0x13820000 // your uart address from downstream device tree
  • CONFIG_LOGLEVEL=8 // log all
  • CONFIG_POSITION_INDEPENDENT - Since Galaxy S8, Samsung randomizes kernel load address. You have to enable this option, if Kernel code start address is random, i.e. changes each boot. Find Kernel code address with cat /proc/iomem
  • CONFIG_LINUX_KERNEL_IMAGE_HEADER - if you want U-boot binary to look as much as Linux kernel image as possible, to pack it inside android boot.img so stock android bootloader can recognize it

Building

Make u-boot

Install arm cross compiler Build:

export CROSS_COMPILE=aarch64-linux-gnu- 
make <$board_name>_defconfig
make

Create android boot image

mkbootimg --base 0x40000000 --kernel_offset 0x00008000 --ramdisk_offset 0x01000000 --tags_offset 0x00000100 --pagesize 2048 --second_offset 0x00f00000 --kernel {path to u-boot.bin} -o {output file}

Replace offsets to your offsets, found from downstream boot.img.

Running

Flash android image, or follow Bootloaders_porting_using_linux guide

Getting uart debug output

Raw

This may be useful, when no C runtime environment set up yet. You should find uart address to write

C

*(volatile unsigned char *)(0x13820020/*uart register to write characters*/) = 0x48; // print H letter

Assembly

mov x26, #0x20 // move 0x13820020 low 16 bit to x26 register
movk x26, #0x1382, lsl #16 // move 0x13820020 high 16 bit to x26 register
mov x27, #0x48 // H letter ascii code
str x27, [x26] // move H to uart register

Using debug() function

You can get debug output from particular *.c file by adding #define DEBUG at the top of file, and calling debug("debug output"); where you need.

Finding base address

Unless you build u-boot with CONFIG_POSITION_INDEPENDENT=y, you should tell u-boot base address, i.e. address in RAM, where stock bootloader load u-boot. This section describes, how to find it.

Without the knowledge of base address u-boot will fail on /common/board_f.c file when calling functions from init_sequence_f. This is a list of initcall addresses, and if CONFIG_SYS_TEXT_BASE does not match with address u-boot resides, you CPU will jump in wrong address and execute irrelevant code, leaving you with unpredictable uart output and results.

cat /proc/iomem | grep "Kernel code" will output something like: 2c0400000-2c0e031d0 : Kernel code

address range start will be your CONFIG_SYS_TEXT_BASE address.

Creating basic device tree

Will contain node for uart driver, fixed clock and chosen.

a5y17lte device tree example

exynos7880.dtsi:

// SPDX-License-Identifier: GPL-2.0+

/dts-v1/;
#include "skeleton.dtsi"
/ {
	compatible = "samsung,exynos7880";

	fin_pll: xxti {
		compatible = "fixed-clock";
		clock-output-names = "fin_pll";
		u-boot,dm-pre-reloc;
		#clock-cells = <0>;
	};

	uart2: serial@13820000 {
		compatible = "samsung,exynos4210-uart";
		reg = <0x13820000 0x100>;
		u-boot,dm-pre-reloc;
	};
};

a5y17lte.dts:

// SPDX-License-Identifier: GPL-2.0+

/dts-v1/;
#include "exynos7880.dtsi"
/ {
	compatible = "samsung,exynos7880";

    aliases {
    	console = &uart2;
    };

    chosen {
        stdout-path = &uart2;
    };
};
 
&fin_pll {
	clock-frequency = <26000000>;
};


Final changes

You may need to comment some serial driver initialization code, as it may not work properly without clock and pinctrl drivers.

Congrats! You should now get a u-boot console prompt!

Testing future u-boot builds

Once you entered in u-boot console, you may upload new u-boot build in RAM via uart and run it

Upload a file into RAM

  • on u-boot console: load{b|x|y|s} <address>. If no address specified, file will be loaded at CONFIG_SYS_LOAD_ADDR
  • exit u-boot console to release tty device

With ckermit

  • install ckermit (build it yourself with `-DSCO_OSR504` flag, for 115200+ baudrates)
  • create a script to send file:
#!/bin/ckermit +

set port /dev/ttyUSB0
set speed 921600
set carrier-watch off
set flow-control none
set prefixing all
send \%1
exit


Source

====

TODO TODO: Figure out how to transfer files from picocom with ymodem or xmodem or gkermit

====

Run uboot test version

On u-boot console: go <address of loaded file>

Hush shell

There is scripting possibility in u-boot with hush shell.

  • Build u-boot with CONFIG_HUSH_PARSER.
  • Write simple uboot_script.sh file like (Note, that empty line in you file will repeat previous command!)
for i in a b c; do
    echo $i
done
  • Make uboot image mkimage -T script -C none -n 'Demo Script File' -d uboot_script.sh uboot_script.img
  • Upload file to RAM as described above
  • Run
    • iminfo <address of loaded script> - check and print script info
    • source <address of loaded script> - run script


Booting linux with u-boot

Usual booting procedure involves loading u-boot's payload from storage to ram, and invoking bootm command. If you don't have storage driver in u-boot for your SoC, you may pack u-boot's payload along with u-boot in one file. That file may be used as stock bootloader's payload. In such case, you should pay attention at CONFIG_SYS_INIT_SP_BSS_OFFSET and CONFIG_SYS_INIT_SP_ADDR options to avoid u-boot early c runtime screw up u-boot's payload. Default values for mentioned options is 512K. Since u-boot's size is usually less than 512K, putting u-boot's payload with 1M offset should be safe, i.e:

cp u-boot.bin stock_payload.bin
dd if=u-boot_payload.bin of=stock_payload.bin seek=1 bs=$((0x100000))

Troubleshooting

Failed to reserve memory...

You may need to increase LMB_MAX_REGIONS config to be higher, than reserved memory regions count in your linux dts. This is because u-boot tries to reserved all reserved memory regions, and it should have regions in lmb library available.

See also