GithubHelp home page GithubHelp logo

p-boot's Introduction

p-boot - pico sized bootloader for PinePhone
--------------------------------------------

Official website: https://xnux.eu/p-boot/

This is a no nonsense bootloader for extremely fast and flexible booting
of PinePhone. p-boot is partly based on some borrowed U-Boot and Linux code.

Some benefits over U-Boot:

- It's very fast (30-60ms boot times + load times for images)
  - Uses MMC DMA, eMMC DDR, and CPU data cache
  - Only minimal necessary boot steps are performed in the most straightforward manner
- It's fail safe and easily debuggable
  - It will power down the device in case of bootloader stage boot failure,
    instead of silently draining the battery
  - Boot status is indicated via LED
    - green  = in bootloader
    - red    = just before passing control to ATF/Linux
    - no led = powered off
  - Bootloader failure is indicated by a 5-bit binary blinking pattern
    (serial port not needed for quick debugging)
  - Bootloader log is stored to DTB, and is visible from Linux via
    `/sys/firmware/devicetree/base/p-boot/log` file
  - Boot log can be printed to the serial port (this will slow down boot)
- It has flexible boot source options
  - Supports multiple boot configurations on SD and eMMC
  - Ability to load bootloader from SD card, but read boot data from eMMC (which
    allows 85MiB/s image load speeds and avoids 1s LED flash activation and 1s boot
    delay waiting for BROM to load bootlader from eMMC)
  - List of available boot configurations is passed to Linux via
    `/sys/firmware/devicetree/base/p-boot/configs` file, so it's easy to make
    a Linux based boot menu.
  - Boot configuration selection via volume keys pressed during boot
    (up to 3 different boot configurations)
  - Allow for default boot config override via a RTC data register (you can reboot
    from one OS to another without user intervention)
  - Support for one time reboot to other OS, or "persistent" change to other
    boot configuration
- It has access to PMIC over RSB (p-boot can access and configure the PMIC)
  - Easy to select alternate boot configuration in case of low battery charge level
  - p-boot configures the PMIC and can react to various boot reasons indicated
    by PMIC
- Single DT blob used by p-boot, ATF and Linux (no U-Boot specific DT blob needed)
- Configure a stable WiFi MAC address in FDT based on SoC ID
- A lot of free space for extensions (p-boot size limit is 32KiB, current
  p-boot size is 31KiB with display support enabled and 25KiB with display support
  disabled)
- Easy to understand and customize

Enjoy!

    Ondřej Jirman (aka "megi")


Future possibilities
--------------------

See TODO for some possible/planned features.


Building
--------

1) Get aarch64-linux-musl cross-compiler and set path to it in config.ini
   (you can use config.ini.sample as a starting point).

2) Then run:

  php configure.php
  ninja

3) As a result you'll get a bunch of p-boot*.bin variants in .build/ dir,
   named p-boot*.bin. See "Variants" section bellow for description
   of each variant.

You may have trouble building p-boot with some toolchains. p-boot is a bit
space constrained and some toolchains don't build it small enough. Known
working toolchains are aarch64 toolchain (gcc 10.2) from community repo
of Arch Linux, and aarch64 toolchain in the latest Ubuntu release.

Building (without PHP)
----------------------

1) Get aarch64-linux-musl cross-compiler and set path to it in
   build/ninja.build by modifying aarch64_prefix.

2) Go to build and run:

  ninja

3) Same as above.


Installation summary / key points
---------------------------------

- PinePhone looks for bootloader 8KiB from the start of SD or eMMC block
  devices, in that order. p-boot.bin needs to be flashed there.
- p-boot doesn't understand traditional filesystems, it uses its own
  very simple boot filesystem format, and comes with a filesystem
  formating utility called p-boot-conf, that is used to create it.
- Once flashed to the boot sector, p-boot will look for the boot
  filesystem in the DOS MBR style partition table (it doesn't understand
  any other partition format).
- So all you need to have is:
  - DOS MBR partition table
  - A boot partition for p-boot. You can re-use a boot partition
    that most distributions create for files in /boot, just copy files from
    /boot to your root partition, unmount /boot, and re-format the boot
    partition using p-boot-conf. You can copy the the original files
    from boot partition back to /boot directory on the root partition,
    so that your distro will not break and keep updating them. Just
    make sure your distro will not overwrite a boot sector during updates
    with U-Boot. (perhaps by uninstalling a u-boot package)


Installation on Arch Linux
--------------------------

See https://github.com/tqre/pinephone-arch


Installing p-boot to the "boot sector"
--------------------------------------

You must install p-boot by copying the contents of p-boot.bin to the SD card
and/or eMMC starting from 8KiB offset from the start of the block device:

  dd if=p-boot.bin of=/dev/mmcblk2 bs=1024 seek=8
  dd if=p-boot.bin of=/dev/mmcblk0 bs=1024 seek=8


ATF / SCP
---------

You'll need a patched ATF that works with p-boot and a SCP firmware build.

You can build these using instructions in the fw/README or use a pre-built
binary from dist/fw.bin (contains combined ATF and SCP binaries).


Boot partition
--------------

p-boot needs to find a specialized boot filesystem on one of the primary MBR
partitions on eMMC or SD card (in that order). p-boot will only search
partitions of type 0x83 (Linux) and it will give priority to partitions
with a boot flag set.

Boot partition contains a table of up to 33 boot configurations. Boot
configuration is a specific set of ATF/SCP firmware, DTB, Linux, and initramfs
images + Linux command line arguments (bootargs).

You can use p-boot-conf tool to create a boot filesystem. You can find this
tool pre-built in the dist/ folder.

This tool reads a 'boot.conf' file from a specified configuration directory
and creates a specialized filesystem on the boot partition based on the
content of these files. You'll need to run this tool each time you'll update
the configuration, or one of the kernel images, to regenerate the boot
filesystem.

Each configuration file has the following format:

  key1=value
  key2=value
  ...

For example:

  no=1
  dtb=board.dtb
  atf=fw.bin
  linux=Image
  initramfs=initramfs.img
  bootargs=console=ttyS0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=f2fs rw rootwait panic=3

Meanings of configuration options:

  - no: Configuration index (0-32)
  - dtb: path to the pinephone's DTB file
  - atf: path to the ATF binary or to the combined ATF+SCP binary (see dist/fw.bin)
  - linux: path to the Linux 'Image' file
  - initramfs: path to initramfs archive
  - bootargs: Linux kernel boot arguments to be passed to the kernel

All options are required except for initramfs. All paths are relative to the
configuration directory.

After preparing the configuration files, and collecting the required binary files
in the configuration directory, run:

  p-boot-conf $conf_dir $boot_partition_block_device

Once done, you can reboot the PinePhone to check that p-boot works. Pre-built
dist/p-boot-conf is meant for running on PinePhone itself. If you need a build
of this tool for another architecture, just run `gcc -o p-boot-conf-native conf.c`
in the `src/` directory.


GUI variant of p-boot
---------------------

GUI variant of p-boot looks for certain hardcoded files in the boot filesystem:

- off.argb     - power off splashscreen
- pboot2.argb  - default p-boot splashscreen

These files can be found in the `example/` configuration, or generated
from source files in the `theme/` directory.


Runtime behavior
----------------

(this is slightly outdated, check main.c for actual behavior)

During powerup or reboot, p-boot will check several places in its decision
making process for selecting the desired boot configuration:

- boot filesystem superblock (32bit BE value at 12 byte offset from the
                              start of boot partition)
- RTC data register (address 0x01f00100)
- PMIC data register (address 0x04)
- Status of the volume keys:
  - VOLUME_UP - no=1
  - VOLUME_DOWN - no=0

Default value is stored in the boot filesystem's superblock. (at offset 12,
4-byte BE value). The value is unchanged by p-boot-conf.

Values in volatile registers are reset to 0 during boot if bit 7 of the value
is set. If the register contains value 0, the value is ignored and doesn't
affect boot configuration selection process. Values other than 0 are
decremented by 1 and the result is used to select the boot configuration.
For example register value 0x03 will select boot configuration 2. Register
value 0x82 will select boot configuration 1 and the register will be
reset to 0 during boot.


Boot process of p-boot is as follows: (also see src/main.c)

- sample the time of the start of the boot
- turn on a green LED
- init various A64 clocks
- enable lradc (to get a sample from volume keys ADC, later on)
- (optional) init debug UART
- init RSB connection to PMIC
- configure PMIC
  - (optional) print PMIC status
  - shorten POK reaction time
  - increase VBUS current limit to 2A and enable charger detection
  - increase CPU voltage to accommodate switch to 1.152GHz later on
- init DRAM
  - setup p-boot heap space for malloc() at 256MiB from end of DRAM
  - enable instruction cache
  - enable MMU/setup CPU data cache
- setup SoC buses
- enable LCD power early so that controller initializes before
  kernel runs, and kernel LCD probe can avoid delays
- disable battery temperature sensor
- program the battery OCV curve for better capacity reporting
- increase CPU clock speed to 1152MHz
- initialize eMMC
  - search for boot partition and load bootfs superblock/conf table
  - if not found repeat the same process on the SD card
- select configuration from the boot table
  - read default boot config selection index from the table
  - apply value from the RTC register
  - apply value from the PMIC register
  - if VOLUME_UP is pressed, force bootsel index = 1
  - if VOLUME_DOWN is pressed, force bootsel index = 0
  - go through the table and load images from the table to:
    - Linux image to 0x40080000
    - initramfs to 0x4fe00000
    - DTB (FDT blob) to 0x4a000000
    - ATF+SCP to 0x44000
- check validity of FDT blob, and in FDT:
  - set /chosen/bootargs to kernel command line
    - append bootdev=emmc or bootdev=sd based on the source of the bootfs
  - calculate MAC address for WiFi from SoC ID and patch it to FDT
  - add DRAM address/size info
  - add initramfs info
- turn off green and turn on red LED
- jump to ATF
  - ATF jumps to Linux image while switching to EL2
  - (alternatively) after return from ATF, jump to Linux image while switching to EL2


Debugging
---------

p-boot will try to fail gracefully in the event of boot failure. This means
that it will try its best to power down the SoC. p-boot also enables the red
LED as early as possible so that the user is informed in case the boot process
hangs that the device is on and drawing power from the battery.

In case of a bootloader panic, p-boot will first blink the red led quickly for
a second and then you'll see 5 flashes of the green LED followed by device poweroff.
The 5 green flashes represent a 5-bit binary number in MSB first bit order.
Long flash represents 1 and short flash represents 0.

You can use this to get the reason for boot failure without the need to pull
out the serial cable. Simply translate the binary number to decimal and search
p-boot code for the panic call with this number. For example, if you get
a flash pattern ". - . - ." -> 0b01010 -> 10:

  grep -R 'panic(10' src

src/main.c:		panic(10, "BOOTFS not found");

That is bootfs was not found. :)


Variants
--------

p-boot can be compiled with several options that improve boot speed,
or reduce size or both.

  p-boot.bin        - GUI variant of p-boot
  p-boot-serial.bin - non-GUI variant, logs to serial console and FDT
  p-boot-tiny.bin   - non-GUI variant, doesn't log anyhting at all,
                      and doesn't store log messages in the binary,
                      so it saves about 5 KiB of space for more code

This is a typical boot log from the p-boot-serial.bin:

% cat /sys/firmware/devicetree/base/p-boot/log

p-boot (version 547db8d-dirty built 2020-05-20 22:55)
384 us: PMIC ready
3492 us: DRAM: 2048 MiB
SoC ID: 92c059ba:14104620:78968308:101a0950
Board rev: 1.2
Boot Source: ff
34065 us: eMMC ready
Trying boot partition located at 0x100000(255 MiB) (part 0)
Bootsel override via RTC data[0] to 5
35500 us: Booting configuration 5 (xnux:Tablet UI test (eMMC))
41228 us: IMG[A]: 0x476e400(61368 B) -> 0x44000 (10466 KiB/s)
41856 us: IMG[D]: 0x477d400(37399 B) -> 0x4a000000 (58342 KiB/s)
196896 us: IMG[L]: 0x4786800(14002184 B) -> 0x40080000 (88197 KiB/s)
Model: Pine64 PinePhone (1.2)
WiFi MAC: 02:ba:7c:9c:cc:78


Bugs and support
----------------

Please report bugs via email:

    [email protected]


Development
-----------

Project status: p-boot is maintained and actively developed by the original
author.

You can join development of p-boot by sending questions, ideas, bugreports
and patches to the above mailing address.

GIT repository is available at: https://megous.com/git/p-boot. 


Support the project
-------------------

p-boot is free and opesource software released under GPLv3. It is an independent
personal project not backed by any comapny or commercial interests. You can
contribute by writing code, helping improve documentation, spreading the word,
and/or by donating at:

  https://xnux.eu/contribute.html

p-boot's People

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

p-boot's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.