[Samsung Gear 2] biktor_gj:
Kernel root switching

As part of all that needs to be done, we need a way to boot to other root device to be able to go into recovery when needed, but not do it everytime. We already have some unused partitions we can use for that, and some others we can repurpose for the task, but, unfortunately, watch's bootloader only appends a string to the kernel command line to make it enter the recovery mode, using the same partition for everything.

So, we need to transform the kernel command line to be able to go into Recovery mode when called from the bootloader, but without touching the bootloader.

I'm posting this so anyone who might be in the same situation has an example on what can be done :)

I came with a simple and ugly solution, but it seems to be working just fine:

When the kernel starts, and before almost anything happens, I read the entire command line, get the necessary pieces, and reassemble it modified before the rest of the kernel uses those variables.

What I do here is simply:

1. Read the command line

2. If the bootloader was asking systemd to enter recovery mode, change the root device to my recovery partition (mmcblk0p8)

3. If it's charging go to the main root device (unfinished) and append a charge-only mode (not done yet, maybe never, not a priority)

4. If it's booting normal mode, change the root device to mmcblk0p9,whcich, hopefully, will have Android root filesystem (the typical initrd)

With this, we can have an independent recovery from the root filesystem, and there's no need to hardcode the full cmdline, managing to retain the serial number for each device.

I also append the 'androidboot.' parameter before serial number, so Android and ADB are able to pick the correct serial number from the device.

It's not completed yet, but according to the kernel logs, it's working ;)

You should put this in either arch/arm/kernel/setup.c or arch/arm/kernel/atags_parse.c, depending on your source tree version

static int __init parse_tag_cmdline(const struct tag *tag)
{
char recoverymode[]="systemd.unit=recovery-mode.target";
char chargemode[]="systemd.unit=charging-mode.target";
char normalboot[]="root=/dev/mmcblk0p9"; // boot init for android, on tizen is p15
char recoveryboot[]="root=/dev/mmcblk0p8";
char fsoptions[]=" ro rootfstype=ext4 rootwait ";
char sec_options[]="sec_debug.enable=0 sec_debug.enable_user=0 sec_watchdog.sec_pet=5 sec_log=0x200000@0x46000000 lcdtype=0 oops=panic pmic_info=1875 sysscope=0xee000000 cordon=224b9a60bc1c844275150b8275305f0b androidboot.";
char console_settings[]="console=ram loglevel=4 g_ffs.idVendor=0x18d1 g_ffs.idProduct=0x4e26 ";
char cmdline_end[256]="\0";
char *serialnumber;
/* Defs end */
memset(default_command_line, 0, sizeof default_command_line);
/* HIJACK THE COMMAND LINE! */

serialnumber=strstr(tag->u.cmdline.cmdline, "serialno");
if (serialnumber!=NULL) // If you can read the serialnumber, pick it
{
strlcpy(cmdline_end, serialnumber, sizeof(cmdline_end));
printk ("\n Serial -- %s", cmdline_end);
}
else // If you don't, act like you did
{
strlcpy(cmdline_end, "serialno=012345678", sizeof(cmdline_end));
printk ("\n Serial -- %s", cmdline_end);
}
if (strstr(tag->u.cmdline.cmdline,recoverymode)!=NULL)
{
printk("\nRECOVERY MODE ***\n");
// boot in recovery mode
strlcpy(default_command_line, console_settings, COMMAND_LINE_SIZE);
strlcat(default_command_line, recoveryboot, COMMAND_LINE_SIZE);
strlcat(default_command_line, fsoptions, COMMAND_LINE_SIZE);
strlcat(default_command_line, sec_options, COMMAND_LINE_SIZE);
strlcat(default_command_line, cmdline_end, COMMAND_LINE_SIZE);
}
else if (strstr(tag->u.cmdline.cmdline,chargemode)!=NULL)
{
printk ("\nCHARGE MODE!! ****\n");
// boot in charge mode
strlcpy(default_command_line, console_settings, COMMAND_LINE_SIZE);
strlcat(default_command_line, recoveryboot, COMMAND_LINE_SIZE);
strlcat(default_command_line, fsoptions, COMMAND_LINE_SIZE);
strlcat(default_command_line, sec_options, COMMAND_LINE_SIZE);
strlcat(default_command_line, cmdline_end, COMMAND_LINE_SIZE);
}
else
{
printk ("\n NORMAL BOOT***\n");
// Normal boot
strlcpy(default_command_line, console_settings, COMMAND_LINE_SIZE);
strlcat(default_command_line, normalboot, COMMAND_LINE_SIZE);
strlcat(default_command_line, fsoptions, COMMAND_LINE_SIZE);
strlcat(default_command_line, sec_options, COMMAND_LINE_SIZE);
strlcat(default_command_line, cmdline_end, COMMAND_LINE_SIZE);
}
/* END HIJACK THE COMMAND LINE */
printk ("\nTransformed command line: %s", default_command_line);
return 0;
}

And the logs retrieved:

NORMAL BOOT

[ 0.000000] [0: swapper: 0] [0] Machine: B2
[ 0.000000] [0: swapper: 0] [0]
[ 0.000000] [0: swapper: 0] [0] Serial -- serialno=******* tizenboot.emmc_checksum=3 tizenboot.odin=1 bootloader.ver=R380XXU0BNL2 bootloader.fb=0x48000000 bootloader.log=0x15be@0x460d077f
[ 0.000000] [0: swapper: 0] [0] NORMAL BOOT***
[ 0.000000] [0: swapper: 0] [0] cma: CMA: reserved 16 MiB at 48000000
[ 0.000000] [0: swapper: 0] [0] cma: CMA: reserved 16 MiB at 5ec00000
[ 0.000000] [0: swapper: 0] [0] Memory policy: ECC disabled, Data cache writealloc
[---]
[ 0.000000] [0: swapper: 0] [0] pcpu-alloc: s8256 r8192 d16320 u32768 alloc=8*4096
[ 0.000000] [0: swapper: 0] [0] pcpu-alloc: [0] 0 [0] 1
[ 0.000000] [0: swapper: 0] [0] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 129794
[ 0.000000] [0: swapper: 0] [0] Kernel command line: console=ram loglevel=4 g_ffs.idVendor=0x18d1 g_ffs.idProduct=0x4e26 root=/dev/mmcblk0p15 ro rootfstype=ext4 rootwait sec_debug.enable=0 sec_debug.enable_user=0 sec_watchdog.sec_pet=5 sec_log=0x200000@0x46000000 lcdtype=0 oops=panic pmic_info=1875 sysscope=0xee000000 cordon=224b9a60bc1c844275150b8275305f0b androidboot.serialno=****** tizenboot.emmc_checksum=3 tizenboot.odin=1 bootloader.ver=R380XXU0BNL2 bootloader.fb=0x48000000 bootloader.log=0x15be@0x460d077f
[ 0.000000] [0: swapper: 0] [0] sec_log_setup: *sec_log_mag:4d474f4c *sec_log_ptr:8d1f9a sec_log_buf:f7200000 sec_log_size:2097152
[ 0.000000] [0: swapper: 0] [0] sec_log_save_old: saved old log at 1048576@c10d2200

RECOVERY MODE

<4>[ 0.000000] [0: swapper: 0] [0] CPU: ARMv7 Processor [410fc073] revision 3 (ARMv7), cr=10c5387d
<4>[ 0.000000] [0: swapper: 0] [0] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
<4>[ 0.000000] [0: swapper: 0] [0] Machine: B2
<4>[ 0.000000] [0: swapper: 0] [0]
<4>[ 0.000000] [0: swapper: 0] [0] Serial -- serialno=****** tizenboot.emmc_checksum=3 tizenboot.odin=1 bootloader.ver=R380XXU0BNL2 bootloader.fb=0x48000000 bootloader.log=0x19b3@0x460f6ca9
<4>[ 0.000000] [0: swapper: 0] [0] RECOVERY MODE ***
<6>[ 0.000000] [0: swapper: 0] [0] cma: CMA: reserved 16 MiB at 48000000
<6>[ 0.000000] [0: swapper: 0] [0] cma: CMA: reserved 16 MiB at 5ec00000
[---]
<7>[ 0.000000] [0: swapper: 0] [0] pcpu-alloc: s8256 r8192 d16320 u32768 alloc=8*4096
<7>[ 0.000000] [0: swapper: 0] [0] pcpu-alloc: [0] 0 [0] 1
<4>[ 0.000000] [0: swapper: 0] [0] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 129794
<5>[ 0.000000] [0: swapper: 0] [0] Kernel command line: console=ram loglevel=4 g_ffs.idVendor=0x18d1 g_ffs.idProduct=0x4e26 root=/dev/mmcblk0p8 ro rootfstype=ext4 rootwait sec_debug.enable=0 sec_debug.enable_user=0 sec_watchdog.sec_pet=5 sec_log=0x200000@0x46000000 lcdtype=0 oops=panic pmic_info=1875 sysscope=0xee000000 cordon=224b9a60bc1c844275150b8275305f0b androidboot.serialno=*********** tizenboot.emmc_checksum=3 tizenboot.odin=1 bootloader.ver=R380XXU0BNL2 bootloader.fb=0x48000000 bootloader.log=0x19b3@0x460f6ca9
<6>[ 0.000000] [0: swapper: 0] [0] sec_log_setup: *sec_log_mag:4d474f4c *sec_log_ptr:8f88cc sec_log_buf:f7200000 sec_log_size:2097152

EDIT:

Aaaand ADB recognizes now the serial number, which is nice ;)

C:\>adb devices
List of devices attached
410021675***** recovery

C:\>

Have fun!