init: Fix writing "reboot recovery" to BCB
When BCB (bootloader message structure inside of misc partition) is malformed (contains some non-printable characters in its fields), "reboot recovery" command won't be able to write required string to "command" field. It can happen for example when partition table was created anew and 'misc' partition area contains some garbage. Also this behavior can be emulated with this command: $ fastboot erase misc which leads to 'misc' partition to be filled with 0xFF characters. Hence this code: if (boot.command[0] == '\0') { won't let us to set new string to "command" field. Let's check if "command" field is malformed and fix it, before actually checking for previously set content. "fastboot erase" shouldn't be used for testing purposes though, as it doesn't work sometimes due to alignment, on bootloader side: Erasing blocks 6144 to 6144 due to alignment ........ erased 0 bytes from 'misc' Instead one might use "dd" command to fill 'misc' with 0xFF's: $ dd if=/dev/zero ibs=2k count=1 | tr "\000" "\377" >misc.img $ fastboot flash misc misc.img Test: Fill 'misc' partition with 0xFF's, then do "adb reboot recovery" Change-Id: Ica8ca31012b9b2249645e7305830c07a20dd013c Signed-off-by: Sam Protsenko <semen.protsenko@linaro.org>
This commit is contained in:
parent
aceb837ced
commit
2c7c3c7402
1 changed files with 25 additions and 1 deletions
|
@ -860,6 +860,30 @@ static void HandleUserspaceReboot() {
|
|||
am.QueueBuiltinAction(handler, "userspace-reboot");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if "command" field is set in bootloader message.
|
||||
*
|
||||
* If "command" field is broken (contains non-printable characters prior to
|
||||
* terminating zero), it will be zeroed.
|
||||
*
|
||||
* @param[in,out] boot Bootloader message (BCB) structure
|
||||
* @return true if "command" field is already set, and false if it's empty
|
||||
*/
|
||||
static bool CommandIsPresent(bootloader_message* boot) {
|
||||
if (boot->command[0] == '\0')
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < arraysize(boot->command); ++i) {
|
||||
if (boot->command[i] == '\0')
|
||||
return true;
|
||||
if (!isprint(boot->command[i]))
|
||||
break;
|
||||
}
|
||||
|
||||
memset(boot->command, 0, sizeof(boot->command));
|
||||
return false;
|
||||
}
|
||||
|
||||
void HandlePowerctlMessage(const std::string& command) {
|
||||
unsigned int cmd = 0;
|
||||
std::vector<std::string> cmd_params = Split(command, ",");
|
||||
|
@ -912,7 +936,7 @@ void HandlePowerctlMessage(const std::string& command) {
|
|||
}
|
||||
// Update the boot command field if it's empty, and preserve
|
||||
// the other arguments in the bootloader message.
|
||||
if (boot.command[0] == '\0') {
|
||||
if (!CommandIsPresent(&boot)) {
|
||||
strlcpy(boot.command, "boot-recovery", sizeof(boot.command));
|
||||
if (std::string err; !write_bootloader_message(boot, &err)) {
|
||||
LOG(ERROR) << "Failed to set bootloader message: " << err;
|
||||
|
|
Loading…
Reference in a new issue