blob: 9cfd94c7289421df7d0d395e85c714ab67cd088a [file] [log] [blame]
/*
* Copyright (C) 2016 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
*
* 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.
*/
#ifndef BUB_AB_FLOW_H_
#define BUB_AB_FLOW_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "bub_ops.h"
/* Magic for the Brillo Uefi metadata header */
#define BUB_BOOT_CTRL_MAGIC {'B', 'U', 'E', 'F'}
/* The current major and minor versions used for AB metadata structs */
#define BUB_MAJOR_VERSION 1
#define BUB_MINOR_VERSION 0
#define BUB_BLOCK_SIZE 512
#define BUB_AB_DATA_SIZE 64
#define BUB_SUFFIX_SIZE 3
typedef enum {
BUB_AB_FLOW_RESULT_OK,
BUB_AB_FLOW_ERROR_INPUT,
BUB_AB_FLOW_ERROR_INVALID_METADATA,
BUB_AB_FLOW_ERROR_NO_VALID_SLOTS,
BUB_AB_FLOW_ERROR_READ_METADATA,
BUB_AB_FLOW_ERROR_WRITE_METADATA
} BubAbFlowResult;
typedef struct {
// Slot priority with 15 meaning highest priority, 1 lowest
// priority and 0 the slot is unbootable.
uint8_t priority: 4;
// Number of times left attempting to boot this slot.
uint8_t tries_remaining: 3;
// 1 if this slot has booted successfully, 0 otherwise.
uint8_t successful_boot: 1;
// Reserved for further use.
uint8_t reserved[7];
} __attribute__((__packed__)) BubSlotData;
/* Bootloader Control BubAbData
*
* This struct is used to manage A/B metadata. Big-endian order is used.
*/
typedef struct {
// Bootloader Control AB magic number (see BUB_BOOT_CTRL_MAGIC).
uint8_t magic[4];
// Major version number.
uint8_t major_version;
// Minor version number.
uint8_t minor_version;
// Reserved for slot alignment.
uint8_t reserved1[2];
// Per-slot information.
BubSlotData slots[2];
// Reserved for further use.
uint8_t reserved2[36];
// CRC32 of all 60 bytes preceding this field.
uint32_t crc32;
} __attribute__((__packed__)) BubAbData;
#if defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 6
_Static_assert(sizeof(BubAbData) == BUB_AB_DATA_SIZE,
"BubAbData has wrong size!");
#endif
/* A/B flow logic for Brillo booting. Reads A/B metadata from the 'misc'
* partition and validates it. Chooses a bootable slot based on its state. Upon
* finding the bootable slot, its "tries remaining" attribute is decremented
* and thus A/B metadata may be modified in the "misc" partition. The suffix of
* a bootable slot, including a terminating NUL-byte, will be written in
* |out_selected_suffix| on success. Caller must specify the size of the
* |out_selected_suffix| in |suffix_num_bytes| which must be at least 3
* otherwise aborting the program. If BUB_AB_FLOW_INVALID_AB_METADATA is
* returned, metadata on disk will be reset to an 'updating' state where both
* slots have tries remaining to reattempt booting.
*
* @return: BUB_AB_FLOW_RESULT_OK on success. BUB_AB_FLOW_INVALID_AB_METADATA
* if AB metadata is invalid. BUB_AB_FLOW_RESULT_ERROR if no available
* memory for allocationor no valid slot found.
*
*/
BubAbFlowResult bub_ab_flow(BubOps* ops,
char* out_selected_suffix,
size_t suffix_num_bytes);
/* Marks a boot slot with |invalid_suffix| invalid by assigning zero to its
* priority, tries_remaining, and successful_boot member variables. Caller
* must pass |invalid_suffix| as a NUL_terminated string with length 2.
*
* @return: 0 on success. 1 on failure.
*/
int bub_ab_mark_as_invalid(BubOps* ops, const char *invalid_suffix);
/* Helper function to read and check validity of AB metadata using |ops|
* read_from_partition method. Will read from "misc" partition and assign
* fields to |data| in host byte order. Checks magic field matches expected
* value and calculates crc32.
*
* @return: BUB_AB_FLOW_ERROR_READ_METADATA on i/o error.
* BUB_AB_FLOW_ERROR_INVALID_METADATA if magic or crc are not
* correct. BUB_AB_FLOW_RESULT_OK on success.
*
*/
BubAbFlowResult bub_read_ab_data_from_misc(BubOps* ops, BubAbData* data);
/* Helper function to write AB metadata using |ops| write_to_partition method.
* Will write to "misc" partition and assign fields to |data| in big-endian byte
* order. Calculates crc32 as well.
*
* @return: 0 on i/o error, 1 on success.
*
*/
int bub_write_ab_data_to_misc(BubOps* ops, const BubAbData* data);
#ifdef __cplusplus
}
#endif
#endif /* BUB_AB_FLOW_H_ */