[Samsung Galaxy Note 8 ROMs, Kernels, Recoveries, &] BigCountry907:
State of Booting Custom Systems

I have made some progress although things are getting a bit more complex.

After spending some time analyzing Safestrap and it's inner workings I do believe that i'm headed in the right direction.

If you view safestrap for what it is ( a boot hijack ) but understand the potential of the method it certainly is our window to get in. Safestrap in a nutshell is a bash script that is executed nearly after the kernel is loaded.

So what does that mean?

Basically the device is booted to a point where bare metal programming techniques can be used.

Bare metal programming involves bringing up the embedded system by compiling the functionality we need into binaries that can be executed at this boot state.

For example if you take a quick look at this book.

Instant Optimizing Embedded System Using BusyBox

You can get it at safari https://www.safaribooksonline.com using a free trial.

It's short to the point and easy to follow.

This shows how we can create a minimal boot image.

Including how to compile busybox and add command functionality to the build then make a ramdisk and init files.

Anything like this is executable using the safestrap method. By safestrap method i mean taking the e2fsck file and writing a shell script to replace it. e2fsck is a filesystem check and run by the system after the kernel is loaded.

So yes you could follow the instructions in that book and boot the N950U into a bash shell on startup.

Now the limitation we have to overcome is dealing with the kernel.

We don't have the ability to hijack the boot process before the kernel is loaded.

Loading a new kernel on top of a running kernel is not the easiest thing to to.

If the stock kernel had loadable module support enabled then we could build the kexec module and load the kernel using kexec. This is how multiboot in safestrap works on devices that can run kexec. But the stock samsung kernel dosen't have loadable module support.

This is where I hope to use U-Boot.

So lets talk about U-Boot a little.

In our case U-Boot is actually a 4th stage bootloader.

The boot sequence is like this.

(System as it is now)

PBL then SBL1 then SBL2 then Little Kernel then android boot.img

(System booting with u-boot)

PBL then SBL1 then SBL2 then Little Kernel then u-boot.img then android boot.img

In a unlocked device the standard boot.img is replaced by U-boot.img. ( NOT U-BOOT .bin ! ).

Be careful differentiating the files of u-boot.

U-boot.bin and U-boot.img are not the same. U-boot.img is the u-boot.bin the kernel and the device tree packed together using (the u-boot version) mkbootimg.

Initially I was hoping that u-boot.img ( the packed U-boot ) was triggered by init like the android boot image is. If that were the case this would be simple because we would boot into safeboot mount the partitions we want to run (SLOT) and then fire init. Essentially the way safestrap runs TWRP recovery.

This is not the case. What happens is little kernel is actually loading U-Boot.bin into ram in place of the android kernel. In a sense you could say U-Boot is the kernel at that point. Once U-Boot.bin is loaded into ram it executes and overwrites itself with the android kernel.

Or interrupting U-Boot during boot will boot into the U-boot shell. From the U-Boot shell we could load anything. ELF, Kernels, Stand alone programs, Literally anything. In a nutshell U-Boot is basically a binary that can load code into any Ram Memory address and start it's execution.

Look at U-Boot in the same sense as the "fastboot boot" command.

Using ( fastboot boot boot.img ) fastboot is loading the boot.img into memory and executing it on the fly.

As example this is the process U-Boot uses to load the linux kernel on the dragonboard.

This is the boot script.

[SIZE="5"][COLOR="Green"]#1[/COLOR][/SIZE][COLOR="RoyalBlue"] it sets up the command line vairable that gets passed to the kernel. Same as commandline in android boot.img.[/COLOR]
bootargs=root=/dev/mmcblk1p1 rw rootwait console=tty0 console=ttyMSM0,115200n8 rootfs=ext4 noinitrd selinux=0

[SIZE="5"][COLOR="SeaGreen"]#2[/COLOR][/SIZE] [COLOR="DeepSkyBlue"]used by u-boot to know what addresses to load the kernel and device tree too.
"bootm" is the command that executes the loading.
[COLOR="red"][SIZE="5"]"ext4load" [/SIZE][/COLOR]and "[SIZE="5"][COLOR="Red"]bootm[/COLOR][/SIZE]" -->> Functions that execute from the loaded u-boot.bin (important)
[/COLOR]
bootcmd=ext4load mmc 1:1 ${kernel_addr_r} /boot/uImage; ext4load mmc 1:1 ${fdt_addr_r} /boot/apq8016-sbc.dtb; bootm ${kernel_addr_r} - ${fdt_addr_r}

[COLOR="SeaGreen"][SIZE="5"]#3[/SIZE][/COLOR] [COLOR="RoyalBlue"]the uenvcmd is executed by the u-boot.bin and is just the variable that is equal to the bootcmd.[/COLOR]
uenvcmd=run bootcmd

So whats the problem here?

We cannot directly execute the u-boot.bin. It's loaded into ram before the kernel.

So lets talk about the environments. By that i mean the boot state of the device.

We have Kernel Space { This is basically commands executed in the kernel }

We have User Space { This is the system after the kernel is loaded and some programs start to run.

We have U-Boot Environment. { This is the device with the U-Boot.bin loaded into Ram before the kernel is loaded.

Normally this is not so important because the normal boot process is loading U-Boot prior to loading the kernel. So normally we start out in the U-Boot environment.

In the U-Boot environment we have access to the ext4load and bootm commands as well as everything else U-Boot contains.

In our case we are in Userspace ( the kernel is loaded already ).

We do not have the ext4load or bootm commands and also the command line ( U-Boot Variables ) do not exist. They exist in the U-Boot environment that we don't have because we haven't loaded u-boot.img we have loaded android boot.img.

This is where things get complicated.

We know that once the kernel is loaded that U-boot.bin no longer exist in RAM. And that's in a normal case where the system was booted with U-Boot initially. Once the kernel is running we are in user space and the u-boot environment is non existent. For our scenario where in that boat. Little kernel has loaded the android kernel.

Now developers being developers of course it makes sense to have the ability to load U-Boot on the fly for testing u-boot builds without flashing the device.

This is how i will proceed to verify the concept.

Loading U-Boot over TFTP.

Not totally ideal but a workable start.

U-Boot implements tftp command to download the kernel and filesystem (in case of ramdisk) images to SDRAM. You can then choose to directly boot the newly downloaded images or write them to non-volatile memory using U-Boot commands and then copy the the images to SDRAM from this memory for subsequent boots.
http://processors.wiki.ti.com/index.php/Booting_Linux_kernel_using_U-Boot

Now the one catch here and maybe i'm wrong but it seems that the device may be booted into the u-boot environment therefore the device or Target is booted to the U-Boot shell and then the Kernel and device tree are loaded over tftp.

https://community.arm.com/dev-platforms/w/docs/236/tftp-remote-network-kernel-using-u-boot

We want to load the linux kernel using u-boot but we have to load u-boot first.

Remember i said u-boot is loaded in place of the kernel.

So rather than tftp the kernel and starting it we are going to tftp the uboot.bin and start it.

This becomes trivial because if you remember we are trying to do this from userspace.

If you also remember u-boot no longer exist in ram after the kernel is loaded.

That means we need to compile the U-Boot functions that are needed to tftp boot into standalone binaries that can be executed from user space. Sounds a bit far out there right.

Not really...we have the source code and in the beginning of this post I linked you to a book that shows you how to take this kind of source and run it on bare metal. It will be a little bit of work though.

So what do we need? Is this even possible?

Looking here answers some questions..

https://blackfin.uclinux.org/doku.php?id=bootloaders:u-boot:tftp_loading_files

Common Examples
u-boot.bin

[COLOR="Red"][SIZE="5"]A common example of using the tftp command is loading up a U-Boot binary to test:[/SIZE][/COLOR]

bfin> tftp 0x1000 u-boot.bin
Using Blackfin EMAC device
TFTP from server 192.168.0.2; our IP address is 192.168.0.15
Filename 'u-boot.bin'.
Load address: 0x1000
Loading: ############################
done
Bytes transferred = 141016 (226d8 hex)
bfin> go 0x1000
## Starting application at 0x00001000 ...

Here we loaded the u-boot.bin file into external memory at address 0x1000. Then we proceeded to simply start executing at that address.

Ok that's getting pretty close but were still not quite there yet.

This is loading u-boot.bin which is what we want to do but it is still doing it from the U-boot environment. "The target is booted to the u-boot shell" ( IN U-BOOT ENV )

The closest to what i'm trying to do so far is exactly this.

https://devtalk.nvidia.com/default/...load-and-boot-from-ram-using-tftpboot-method/

Everything is just about working in that thread except the guy needs to set the cpu registers.

We may or may not run into that since where taking the device almost to bare metal using safestrap. We will need to set up some environment variables and possibly set some cpu registers.

Im thinking that we are going to need to build some of the u-boot functions as standalone binaries. Fortunately this is easy for some functions. If we tie these functions into the safestrap boot using the method contained in the previously mentioned book that may work. We also have the option of possibly adding these functions into the busybox binary.

Here is a example that we will need to follow to set u-boot environment variables from userspace.

https://www.denx.de/wiki/DULG/HowCanIAccessUBootEnvironmentVariablesInLinux

So in a nutshell that is abut where i am at.

I have a dragonboard to test on to prove the concept.

I compiled u-boot last night so im about ready to get testing.

This way i can get u-boot up and running properly on the dragon.

I will start out the normal way by flashing u-boot.img to the boot.img partition.

After all is well and working correctly I can set up dragonboard like the Note 8.

Port safestrap type hijack to the dbragon then try to load the know working u-boot from the safestrap environment. Once this is working its just a matter of porting things over to the note 8.