Looking in the android source for the reboot command we find the following line:
__reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, \
LINUX_REBOOT_CMD_RESTART2, argv[optind]);
Which is the standard Linux system call to reboot the system with a specific command, see Unix System Call Reboot.
In Android this command is used to tell the bootloader to start either the kernel in recovery mode or to go to the fastboot mode within the bootloader.
My question is: How does the bootloader pick up the command? And is this functionality implemented in U-Boot? (I am unable to find it searching either through Google or in the U-Boot source.)
Additionally it seems this is not specific to Android, but is the way Linux performs a "reboot with a command". Any information on how this is "normally" handled/used in Linux?
When the system is rebooted using LINUX_REBOOT_CMD_RESTART2
, the supplied command string is passed to all of the notifiers registered with register_reboot_notifer()
, and finally to machine_restart()
- the architecture-specific function that actually performs system restart.
Most architectures ignore the passed command entirely - for an example of one that doesn't, see SPARC. The SPARC implementation of machine_restart()
passes the supplied string to the boot
command of the PROM.
The ARM implementation of machine_restart()
ends up passing the supplied command to arch_reset()
which is implemented separately on each ARM platform - from what I can see, most if not all of those implementations ignore the passed command, at least in the upstream kernel. This may not be the droid you're looking for.
I have no clue how they do it in Android, but on our systems where we use u-boot as well we have a similar mechanism.
We reserve a very small memory portion that is reserved for "communication" from bootloader to kernel and the opposite direction as well. If this memory can survive a reboot (put the RAM in self-refresh mode before rebooting, or in Flash), it's then easy to read the value in the bootloader start and to determine if you have to start the kernel and then your system usually or you want to go to a special mode of the bootloader.
Write "boot-recovery" command in MSC partiton. The bootloader reads the string from MSC partition and loads the recovery kernel. This was the way the recovery kernel was loaded in Froyo and before. The same approach can be followed in GB/HC/ICS.
Another method is to carve out some memory and pass some flag which is read from he bootloader. The only issue is that the DRAM contents might get lost during reboot unless you put SDRAM in self refesh mode. So during restart this needs to be taken care of.
First method is useful when the power goes off during the update process. In this case the device need to go into recovery kernel again. In that case MSC partition must be cleared only after whole update process is successful.
On some ARM processors the running kernel sets a flag in one of the CPU registers which is then read by UBOOT keep in mind this stuff if very hardware specific.