Android systems use a so-called "bootloader control block" to
coordinate between the bootloader and the recovery system (which handles
factory resets, system updates, firmware updates, etc.). The BCB is
traditionally either an MTD device or an eMMC partition, and it contains
a struct bootloader_message directly on the device/partition. The
recovery system will write a message into the control block, which the
bootloader is then meant to check to see if it should boot into recovery
mode or normal mode (the idea being that the control block is only
cleared once recovery is finished, ensuring fault-tolerance; if the
device is powered off mid-update, it will boot back into the same
recovery mode). 

This module exports the bcb fields as env variables.
First the user sets android_bcb_disk to the partition containing the BCB
(I don't know how to support MTDs yet but I only deal with x86). Then
variables such as android_bcb_command and android_bcb_recovery can be
checked and used to determine which mode to boot into. They can also, if
necessary, be modified by setting the variables in question. The typical
use case will probably be to check if there is a recovery command
present and if so boot into recovery mode. 

Does that explain enough?


Thanks,
Shea 

On 2016-01-31 18:41, Vladimir 'phcoder' Serbinenko
wrote: 

> Sorry but I don't quite understand what this module is for.
Can you please give an example of how it's used both in original context
and in GRUB. I have couple of style comments as well but clarifying the
usecase first is important. 
> 
> Le lun. 1 févr. 2016 00:01, Shea Levy
<s...@shealevy.com> a écrit : 
> 
>> ---
>> grub-core/Makefile.core.def
| 5 ++
>> grub-core/android/android_bcb.c | 163
++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 168
insertions(+)
>> create mode 100644 grub-core/android/android_bcb.c
>>

>> diff --git a/grub-core/Makefile.core.def
b/grub-core/Makefile.core.def
>> index 0cc40bb..b045ea4 100644
>> ---
a/grub-core/Makefile.core.def
>> +++ b/grub-core/Makefile.core.def
>> @@
-2327,3 +2327,8 @@ module = {
>> common = loader/i386/xen_file64.c;
>>
extra_dist = loader/i386/xen_fileXX.c;
>> };
>> +
>> +module = {
>> +
name = android_bcb;
>> + common = android/android_bcb.c;
>> +};
>> diff
--git a/grub-core/android/android_bcb.c
b/grub-core/android/android_bcb.c
>> new file mode 100644
>> index
0000000..db49446
>> --- /dev/null
>> +++
b/grub-core/android/android_bcb.c
>> @@ -0,0 +1,163 @@
>> +/*
android_bcb.c - module for interacting with the android bootloader
control block */
>> +/*
>> + * GRUB -- GRand Unified Bootloader
>> + *
Copyright (C) 2016 Free Software Foundation, Inc.
>> + *
>> + * GRUB is
free software: you can redistribute it and/or modify
>> + * it under the
terms of the GNU General Public License as published by
>> + * the Free
Software Foundation, either version 3 of the License, or
>> + * (at your
option) any later version.
>> + *
>> + * GRUB is distributed in the hope
that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even
the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more
details.
>> + *
>> + * You should have received a copy of the GNU
General Public License
>> + * along with GRUB. If not, see
<http://www.gnu.org/licenses/ [1]>.
>> + */
>> +
>> +#include
<stddef.h>
>> +
>> +#include <grub/dl.h>
>> +#include <grub/env.h>
>>
+#include <grub/disk.h>
>> +
>> +GRUB_MOD_LICENSE ("GPLv3+");
>> +
>>
+/* Definition of struct bootloader message from
https://android.googlesource.com/platform/bootable/recovery/+/9d72d4175b06a70c64c8867ff65b3c4c2181c9a9/bootloader.h#20
[2]
>> + * Available under the following copyright and terms:
>> + *
>>
+ * Copyright (C) 2008 The Android Open Source Project
>> + *
>> + *
Licensed under the Apache License, Version 2.0 (the "License");
>> + *
you may not use this file except in compliance with the License.
>> + *
You may obtain a copy of the License at
>> + *
>> + *
http://www.apache.org/licenses/LICENSE-2.0 [3]
>> + *
>> + * Unless
required by applicable law or agreed to in writing, software
>> + *
distributed under the License is distributed on an "AS IS" BASIS,
>> + *
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
>> + * See the License for the specific language governing
permissions and
>> + * limitations under the License.
>> + */
>> +struct
bootloader_message
>> +{
>> + char command[32];
>> + char status[32];
>>
+ char recovery[768];
>> + // The 'recovery' field used to be 1024
bytes. It has only ever
>> + // been used to store the recovery command
line, so 768 bytes
>> + // should be plenty. We carve off the last 256
bytes to store the
>> + // stage string (for multistage packages) and
possible future
>> + // expansion.
>> + char stage[32];
>> + char
slot_suffix[32];
>> + char reserved[192];
>> +} GRUB_PACKED;
>> +
>>
+struct bcb_state
>> +{
>> + grub_disk_t disk;
>> + char
internal_write;
>> + struct bootloader_message msg;
>> +};
>> +
>>
+static struct bcb_state state = { 0 };
>> +
>> +#define
SET_FIELD(field) 
>> + state.msg. field[sizeof state.msg. field - 1] =
''; 
>> + grub_env_set ("android_bcb_" #field, state.msg. field)
>> +
>>
+static void open_disk (const char *name) {
>> + if (state.disk) {
>> +
grub_disk_close (state.disk);
>> + }
>> +
>> + state.disk =
grub_disk_open (name);
>> + if (state.disk) {
>> + grub_err_t err =
grub_disk_read (state.disk, 0, 0, sizeof state.msg,
>> + &state.msg);
>>
+ if (err) {
>> + grub_disk_close (state.disk);
>> + state.disk = 0;
>>
+ } else {
>> + state.internal_write = 1;
>> + SET_FIELD (command);
>> +
SET_FIELD (status);
>> + SET_FIELD (recovery);
>> + SET_FIELD
(stage);
>> + SET_FIELD (slot_suffix);
>> + state.internal_write = 0;
>>
+ }
>> + }
>> +}
>> +
>> +#define MAYBE_UPDATE_FIELD(field) 
>> + do {
if (!grub_strcmp (var->name, "android_bcb_" #field)) 
>> + { 
>> +
grub_memcpy (state.msg. field, val, sizeof state.msg. field - 1); 
>> +
state.msg. field[sizeof state.msg. field - 1] = ''; 
>> +
grub_disk_write (state.disk, 0, 
>> + offsetof (struct
bootloader_message, field), 
>> + sizeof state.msg. field, state.msg.
field); 
>> + } } while (0)
>> +
>> +static char *handle_write (struct
grub_env_var *var,
>> + const char *val)
>> +{
>> + if (!grub_strcmp
(var->name, "android_bcb_disk"))
>> + {
>> + open_disk (val);
>> + if
(!state.disk)
>> + grub_print_error ();
>> + }
>> + else if (state.disk
&& !state.internal_write)
>> + {
>> + MAYBE_UPDATE_FIELD (command);
>> +
MAYBE_UPDATE_FIELD (status);
>> + MAYBE_UPDATE_FIELD (recovery);
>> +
MAYBE_UPDATE_FIELD (stage);
>> + MAYBE_UPDATE_FIELD (slot_suffix);
>> +
}
>> +
>> + return grub_strdup (val);
>> +}
>> +
>>
+GRUB_MOD_INIT(android_bcb)
>> +{
>> + const char *disk = grub_env_get
("android_bcb_disk");
>> + if (disk)
>> + {
>> + open_disk (disk);
>> +
if (!state.disk)
>> + grub_print_error ();
>> + }
>> +
>> + if
(!grub_register_variable_hook ("android_bcb_disk", 0, handle_write))
>>
+ grub_print_error ();
>> + if (grub_register_variable_hook
("android_bcb_command", 0, handle_write))
>> + grub_print_error ();
>> +
if (grub_register_variable_hook ("android_bcb_status", 0,
handle_write))
>> + grub_print_error ();
>> + if
(grub_register_variable_hook ("android_bcb_recovery", 0,
handle_write))
>> + grub_print_error ();
>> + if
(grub_register_variable_hook ("android_bcb_stage", 0, handle_write))
>>
+ grub_print_error ();
>> + if (grub_register_variable_hook
("android_bcb_slot_suffix", 0, handle_write))
>> + grub_print_error
();
>> +}
>> +
>> +GRUB_MOD_FINI(android_bcb)
>> +{
>> +
grub_register_variable_hook ("android_bcb_disk", 0, 0);
>> +
grub_register_variable_hook ("android_bcb_command", 0, 0);
>> +
grub_register_variable_hook ("android_bcb_status", 0, 0);
>> +
grub_register_variable_hook ("android_bcb_recovery", 0, 0);
>> +
grub_register_variable_hook ("android_bcb_stage", 0, 0);
>> +
grub_register_variable_hook ("android_bcb_slot_suffix", 0, 0);
>> +
>> +
if (state.disk)
>> + grub_disk_close (state.disk);
>> +}
>> --
>>
2.7.0
>> 
>> _______________________________________________
>>
Grub-devel mailing list
>> Grub-devel@gnu.org
>>
https://lists.gnu.org/mailman/listinfo/grub-devel [4]




Links:
------
[1] http://www.gnu.org/licenses/
[2]
https://android.googlesource.com/platform/bootable/recovery/+/9d72d4175b06a70c64c8867ff65b3c4c2181c9a9/bootloader.h#20
[3]
http://www.apache.org/licenses/LICENSE-2.0
[4]
https://lists.gnu.org/mailman/listinfo/grub-devel
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to