Hi Igor,

Thank you for the patch.

On Mon, Oct 12, 2026 at 22:25, Igor Opaniuk <[email protected]> 
wrote:

> Android's fastboot client changes the device lock state with
> "fastboot flashing lock|unlock" and asks "flashing get_unlock_ability"
> first. U-Boot has the state in the AVB TA (avb_write_lock_state(), used by
> the "avb lock/unlock" shell commands) but no fastboot front end for it, so
> a device could only be unlocked from the serial console.
>
> Add the three commands and the "unlocked" variable behind
> CONFIG_FASTBOOT_CMD_FLASHING. As AVB requires, both transitions erase
> userdata (and metadata, which holds the file based encryption keys) before
> the state changes and are refused when userdata cannot be erased; the TA
> resets the rollback indexes on a state change. get_unlock_ability always
> reports 1 since U-Boot does not evaluate the "OEM unlocking" setting
> Android keeps in the frp partition.
>
> Tested on QEMU virt with OP-TEE over "fastboot tcp": unlock and lock
> erase the partitions and flip the state reported by getvar unlocked and
> "avb is_unlocked".
>
> Signed-off-by: Igor Opaniuk <[email protected]>
> ---
>  drivers/fastboot/Kconfig      |  11 ++++
>  drivers/fastboot/fb_command.c | 119 
> ++++++++++++++++++++++++++++++++++++++++++
>  drivers/fastboot/fb_getvar.c  |  34 ++++++++++++
>  include/fastboot.h            |   3 ++
>  4 files changed, 167 insertions(+)
>

[...]

> +}
> +
> +/**
> + * flashing_get_unlock_ability() - report whether unlocking is allowed
> + *
> + * Android gates this on the "OEM unlocking" developer setting, stored by
> + * the OS in the frp partition; there is no policy for it in U-Boot, so
> + * unlocking is always possible.
> + */
> +static void flashing_get_unlock_ability(char *cmd_parameter, char *response)
> +{
> +     fastboot_okay("1", response);
> +}
> +#endif /* FASTBOOT_CMD_FLASHING */
> diff --git a/drivers/fastboot/fb_getvar.c b/drivers/fastboot/fb_getvar.c
> index e8aa0e09aa6..92c8e702a0b 100644
> --- a/drivers/fastboot/fb_getvar.c
> +++ b/drivers/fastboot/fb_getvar.c
> @@ -28,6 +28,7 @@ static void getvar_has_slot(char *var_parameter, char 
> *response);
>  static void getvar_partition_type(char *part_name, char *response);
>  static void getvar_partition_size(char *part_name, char *response);
>  static void getvar_is_userspace(char *var_parameter, char *response);
> +static void getvar_unlocked(char *var_parameter, char *response);
>  
>  static const struct {
>       const char *variable;
> @@ -88,6 +89,10 @@ static const struct {
>               .dispatch = getvar_partition_size,
>               .list = false
>  #endif
> +     }, {
> +             .variable = "unlocked",
> +             .dispatch = CONFIG_IS_ENABLED(FASTBOOT_CMD_FLASHING, 
> (getvar_unlocked), (NULL)),
> +             .list = CONFIG_IS_ENABLED(FASTBOOT_CMD_FLASHING)

.list is only to decide if we need to display the unlocked variable when
a user runs 'fastboot getvar all'

In the case of FASTBOOT_CMD_FLASHING not being set, the "unlocked"
variable will still be available, but .dispatch will be a
NULL function.

Thus, `fastboot getvar unlocked` can still be called and in
fastboot_getvar() we have:

        getvar_dispatch[i].dispatch(var_parameter,
                                    response);

Which will call a NULL function pointer.

To avoid this issue, can we guard the unlocked section similarly to
other variables, such as 'has-slot' ?

Thanks
Mattijs

Reply via email to