| /** |
| * Copyright (c) 2020 The Fuchsia Authors. |
| * |
| * SPDX-License-Identifier: BSD-3-Clause |
| * |
| * The header file defines structures and functions for supporting abr wear-leveling |
| * algorithm. The logic are written in C as it needs to be used in both OS |
| * and bootloader. |
| */ |
| |
| #ifndef ABR_WEAR_LEVELING_H_ |
| #define ABR_WEAR_LEVELING_H_ |
| |
| #include <common.h> |
| |
| #include "sysconfig-header.h" |
| |
| #define ABR_WEAR_LEVELING_ABR_DATA_SIZE 32 |
| #define ABR_WEAR_LEVELING_MAGIC_OFFSET ABR_WEAR_LEVELING_ABR_DATA_SIZE |
| #define ABR_WEAR_LEVELING_MAGIC_LEN 4 |
| #define ABR_WEAR_LEVELING_MAGIC_BYTE_0 0xaa |
| #define ABR_WEAR_LEVELING_MAGIC_BYTE_1 0x55 |
| #define ABR_WEAR_LEVELING_MAGIC_BYTE_2 0x11 |
| #define ABR_WEAR_LEVELING_MAGIC_BYTE_3 0x22 |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /** |
| * Abr metadata extended with a magic for wear-leveling. |
| * Though abr metadata itself comes with a magic. Here we use a separate magic |
| * to avoid exposing internal detail of abr logic to wear-leveling algorithm. |
| */ |
| struct abr_metadata_ext { |
| uint8_t abr_data[ABR_WEAR_LEVELING_ABR_DATA_SIZE]; |
| uint8_t magic[ABR_WEAR_LEVELING_MAGIC_LEN]; |
| } __attribute__((packed)); |
| |
| /** |
| * Checks whether an abr metadata page is valid in the context of wear-levelingn |
| * It simply checks the magic in abr_metadata_ext. |
| * |
| * Return true if valid, false otherwise. |
| */ |
| bool abr_metadata_page_valid(const struct abr_metadata_ext *abr_data); |
| |
| /** |
| * Checks whether the sysconfig layout specified by <header> supports abr wear-leveling. |
| * |
| * Returns true if it supports, false otherwise. |
| */ |
| bool layout_support_wear_leveling(const struct sysconfig_header *header, |
| size_t page_size); |
| |
| /** |
| * Finds the latest abr metadata in abr sub-partition given as a memory buffer. |
| * Copies the new data into <out>. The function will check the magic in each page. |
| * If no page contains valid magic, it copies from the first page. |
| * |
| * Returns the page index where the latest page resides. |
| * |
| */ |
| int find_latest_abr_metadata_page(const struct sysconfig_header *header, |
| const void *abr_subpart, uint64_t page_size, |
| struct abr_metadata_ext *out); |
| /** |
| * Finds an valid empty page for appending new abr metadata. |
| * The requirement of consecutive page programming is met by trying to find the |
| * immediate empty page after the last non-empty page in the sub-partition. |
| * |
| * Returns true if there is an empty page to write. The page index will be assigned |
| * to <out>. Returns false otherwise. |
| */ |
| bool find_empty_page_for_wear_leveling(const struct sysconfig_header *header, |
| const uint8_t *abr_subpart, |
| uint64_t page_size, int64_t *out); |
| |
| /** |
| * Set the magic field of the given abr_metadata_ext struct. |
| * |
| */ |
| void set_abr_metadata_ext_magic(struct abr_metadata_ext *data); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif // LIB_SYSCONFIG_ABR_WEAR_LEVELING_H_ |