Skip to content

Commit

Permalink
boot_info: A subsystem to share bootloader info
Browse files Browse the repository at this point in the history
boot_info is a simple subsystem to share information between a
bootloader and an application. It can store the info in a bbram device
or a zephyr,memory-region (RAM).

Signed-off-by: Laczen JMS <laczenjms@gmail.com>
  • Loading branch information
Laczen committed Jun 21, 2023
1 parent 785d9bd commit 1715133
Show file tree
Hide file tree
Showing 20 changed files with 434 additions and 0 deletions.
15 changes: 15 additions & 0 deletions dts/bindings/misc/zephyr,boot-info-bbram.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright (c) 2023 Laczen
# SPDX-License-Identifier: Apache-2.0

description: Boot information area stored on bbram

compatible: "zephyr,boot-info-bbram"

include: base.yaml

properties:
backend:
type: phandle
required: true
description: |
Battery backend-up ram used to store the bootinfo.
15 changes: 15 additions & 0 deletions dts/bindings/misc/zephyr,boot-info-ram.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright (c) 2023 Laczen
# SPDX-License-Identifier: Apache-2.0

description: Boot information area stored on ram

compatible: "zephyr,boot-info-ram"

include: base.yaml

properties:
backend:
type: phandle
required: true
description: |
Memory region used to store the bootinfo.
102 changes: 102 additions & 0 deletions include/zephyr/boot_info/boot_info.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright (c) 2023 Laczen
* SPDX-License-Identifier: Apache-2.0
*/

/**
* @file
* @brief Public API for boot_info subsys
*/

#ifndef ZEPHYR_INCLUDE_BOOT_INFO_BOOT_INFO_H_
#define ZEPHYR_INCLUDE_BOOT_INFO_BOOT_INFO_H_

#include <zephyr/kernel.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief boot_info api
*
* @defgroup boot_info_api boot_info Interface
* @ingroup storage_apis
* @{
*/

/**
* @brief boot_info: subsystem to share information between a bootloader and
* and application started from the bootloader. The boot_info subsystem uses
* stores it information in a area of RAM (a zephyr, memory-region) or a bbram
* device. To save valuable rom space this subsystem does not create devices.
*
* The usage pattern of the boot_info system is:
* a. Create a array for the boot_info data:
* uint8_t data[boot_info_get_size(DT_NODELABEL(boot_info))];
* b. Get the boot_info data:
* int rc = boot_info_get(DT_NODELABEL(boot_info), data);
* c. Modify the data (optional)
* d. Write back the data (optional):
* int rc = boot_info_set(DT_NODELABEL(boot_info), data);
*
* For bbram storage the boot_info is defined in the dts as:
* / {
* boot_info: boot_info {
* compatible = "zephyr, boot-info-bbram";
* backend = <&bbram>; # bbram node: bbram
* };
* }
*
* For ram storage the boot_info is defined in the dts as:
* / {
* boot_info: boot_info {
* compatible = "zephyr, boot-info-ram";
* backend = <&mem-region>; # mem-region: mem-region node
* };
*/

/**
* @brief boot_info_get_size: Get the size of the boot_info area.
*
* @param _node: nodelabel of the boot_info area (e.g. DT_NODELABEL(boot_info)).
* @retval size of the boot_info area.
*/
#define boot_info_get_size(_node) _CONCAT(bi_get_size_, _node)()

/**
* @brief boot_info_get: Get the boot_info area.
*
* @param _node: nodelabel of the boot_info area (e.g. DT_NODELABEL(boot_info)).
* @param [out] _data: buffer for the boot_info area.
* @retval 0 on success, negative error code if error.
*/
#define boot_info_get(_node, _data) _CONCAT(bi_get_, _node)(_data)

/**
* @brief boot_info_set: Set the boot_info area.
*
* @param _node: nodelabel of the boot_info area (e.g. DT_NODELABEL(boot_info)).
* @param [in] _data: buffer for the boot_info area.
* @retval 0 on success, negative error code if error.
*/
#define boot_info_set(_node, _data) _CONCAT(bi_set_, _node)(_data)

/**
* @}
*/

#define DEFINE_BOOT_INFO_PROTO(inst) \
size_t bi_get_size_##inst(void); \
int bi_get_##inst(void *data); \
int bi_set_##inst(const void *data);

DT_FOREACH_STATUS_OKAY(zephyr_boot_info_ram, DEFINE_BOOT_INFO_PROTO)

DT_FOREACH_STATUS_OKAY(zephyr_boot_info_bbram, DEFINE_BOOT_INFO_PROTO)

#ifdef __cplusplus
}
#endif

#endif /* ZEPHYR_INCLUDE_BOOT_INFO_BOOT_INFO_H_ */
1 change: 1 addition & 0 deletions subsys/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ add_subdirectory_ifdef(CONFIG_SHELL shell)
add_subdirectory_ifdef(CONFIG_TIMING_FUNCTIONS timing)
add_subdirectory_ifdef(CONFIG_ZBUS zbus)
add_subdirectory_ifdef(CONFIG_ARM_SIP_SVC_SUBSYS sip_svc)
add_subdirectory_ifdef(CONFIG_BOOT_INFO boot_info)
1 change: 1 addition & 0 deletions subsys/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
menu "Subsystems and OS Services"

source "subsys/bluetooth/Kconfig"
source "subsys/boot_info/Kconfig"
source "subsys/canbus/Kconfig"
source "subsys/console/Kconfig"
source "subsys/debug/Kconfig"
Expand Down
4 changes: 4 additions & 0 deletions subsys/boot_info/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) 2023 Laczen
# SPDX-License-Identifier: Apache-2.0

zephyr_sources_ifdef(CONFIG_BOOT_INFO boot_info.c)
16 changes: 16 additions & 0 deletions subsys/boot_info/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Copyright (c) 2023 Laczen
# SPDX-License-Identifier: Apache-2.0

menuconfig BOOT_INFO
bool "Boot Information Area"
help
Enable boot information area access with different backend solutions.
The boot information area can be stored on bbram, ram, ...

if BOOT_INFO

module = BOOT_INFO
module-str = boot_info
source "subsys/logging/Kconfig.template.log_config"

endif # BOOT_INFO
101 changes: 101 additions & 0 deletions subsys/boot_info/boot_info.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Copyright (c) 2023 Laczen
* SPDX-License-Identifier: Apache-2.0
*/

#include <string.h>
#include <errno.h>
#include <zephyr/kernel.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/bbram.h>
#include <zephyr/boot_info/boot_info.h>

#define BACKEND_PHANDLE(inst) DT_PHANDLE(inst, backend)

#define BACKEND_K_SEM_DEFINE(inst) \
COND_CODE_1(CONFIG_MULTITHREADING, \
(static K_SEM_DEFINE(k_sem_##inst, 1, 1)), ())

#define BACKEND_K_SEM_TAKE(inst) \
COND_CODE_1(CONFIG_MULTITHREADING, \
(k_sem_take(&k_sem_##inst, K_FOREVER)), ())

#define BACKEND_K_SEM_GIVE(inst) \
COND_CODE_1(CONFIG_MULTITHREADING, (k_sem_give(&k_sem_##inst)), ())

#define RAM_BACKEND_FCNTS(inst) \
BACKEND_K_SEM_DEFINE(inst); \
size_t bi_get_size_##inst(void) \
{ \
return DT_REG_SIZE(BACKEND_PHANDLE(inst)); \
} \
int bi_get_##inst(void *data) \
{ \
BACKEND_K_SEM_TAKE(inst); \
memcpy(data, (uint8_t *)DT_REG_ADDR(BACKEND_PHANDLE(inst)), \
DT_REG_SIZE(BACKEND_PHANDLE(inst))); \
BACKEND_K_SEM_GIVE(inst); \
return 0; \
} \
int bi_set_##inst(const void *data) \
{ \
BACKEND_K_SEM_TAKE(inst); \
memcpy((uint8_t *)DT_REG_ADDR(BACKEND_PHANDLE(inst)), data, \
DT_REG_SIZE(BACKEND_PHANDLE(inst))); \
BACKEND_K_SEM_GIVE(inst); \
return 0; \
}

DT_FOREACH_STATUS_OKAY(zephyr_boot_info_ram, RAM_BACKEND_FCNTS)

#define BBRAM_BACKEND_FCNTS(inst) \
BACKEND_K_SEM_DEFINE(inst); \
const struct device *const bi_dev_##inst = \
DEVICE_DT_GET_OR_NULL(BACKEND_PHANDLE(inst)); \
size_t bi_get_size_##inst(void) \
{ \
if (!device_is_ready(bi_dev_##inst)) { \
return 0U; \
} \
\
size_t bbram_size = 0; \
int rc; \
BACKEND_K_SEM_TAKE(inst); \
rc = bbram_get_size(bi_dev_##inst, &bbram_size); \
BACKEND_K_SEM_GIVE(inst); \
return (rc == 0) ? bbram_size : 0U; \
} \
int bi_get_##inst(void *data) \
{ \
if (!device_is_ready(bi_dev_##inst)) { \
return -ENODEV; \
} \
\
size_t bbram_size = 0; \
int rc; \
BACKEND_K_SEM_TAKE(inst); \
rc = bbram_get_size(bi_dev_##inst, &bbram_size); \
if (rc == 0) { \
rc = bbram_read(bi_dev_##inst, 0, bbram_size, data); \
} \
BACKEND_K_SEM_GIVE(inst); \
return rc; \
} \
int bi_set_##inst(const void *data) \
{ \
if (!device_is_ready(bi_dev_##inst)) { \
return -ENODEV; \
} \
\
size_t bbram_size = 0; \
int rc; \
BACKEND_K_SEM_TAKE(inst); \
rc = bbram_get_size(bi_dev_##inst, &bbram_size); \
if (rc == 0) { \
rc = bbram_write(bi_dev_##inst, 0, bbram_size, data); \
} \
BACKEND_K_SEM_GIVE(inst); \
return rc; \
}

DT_FOREACH_STATUS_OKAY(zephyr_boot_info_bbram, BBRAM_BACKEND_FCNTS)
9 changes: 9 additions & 0 deletions tests/subsys/boot_info/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (c) 2023 Laczen
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.20.0)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(boot_info_test)

target_sources(app PRIVATE src/main.c)
4 changes: 4 additions & 0 deletions tests/subsys/boot_info/boards/native_posix.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) 2023 Laczen
# SPDX-License-Identifier: Apache-2.0
CONFIG_BBRAM=y
CONFIG_BBRAM_EMUL=y
21 changes: 21 additions & 0 deletions tests/subsys/boot_info/boards/native_posix.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright (c) 2023 Laczen
* SPDX-License-Identifier: Apache-2.0
*/

/ {
bbram_emu: bbram_emu {
compatible = "zephyr,bbram-emul";
size = <0x20>;
};

boot_info: boot_info {
compatible = "zephyr,boot-info-bbram";
backend = <&bbram_emu>;
};

aliases {
bi = &boot_info;
};

};
5 changes: 5 additions & 0 deletions tests/subsys/boot_info/boards/nucleo_f411re.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright (c) 2023 Laczen
# SPDX-License-Identifier: Apache-2.0
CONFIG_BBRAM=y
CONFIG_COUNTER=y
CONFIG_BBRAM_STM32=y
20 changes: 20 additions & 0 deletions tests/subsys/boot_info/boards/nucleo_f411re.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright (c) 2023 Laczen
* SPDX-License-Identifier: Apache-2.0
*/

&bbram {
status = "okay";
};

/ {
boot_info: boot_info {
compatible = "zephyr,boot-info-bbram";
backend = <&bbram>;
};

aliases {
bi = &boot_info;
};

};
3 changes: 3 additions & 0 deletions tests/subsys/boot_info/boards/qemu_cortex_m3.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Copyright (c) 2023 Laczen
# SPDX-License-Identifier: Apache-2.0
CONFIG_USERSPACE=y
28 changes: 28 additions & 0 deletions tests/subsys/boot_info/boards/qemu_cortex_m3.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2023 Laczen
* SPDX-License-Identifier: Apache-2.0
*/

#include <common/mem.h>

/ {
bi_region: sram@2000FFE0 {
compatible = "zephyr,memory-region", "mmio-sram";
reg = <0x2000FFE0 0x20>;
zephyr,memory-region = "BI_REGION";
};

boot_info: boot_info {
compatible = "zephyr,boot-info-ram";
backend = <&bi_region>;
};

aliases {
bi = &boot_info;
};

};

&sram0 {
reg = <0x20000000 0xFFE0>;
};
4 changes: 4 additions & 0 deletions tests/subsys/boot_info/boards/qemu_x86.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) 2023 Laczen
# SPDX-License-Identifier: Apache-2.0
CONFIG_BBRAM=y
CONFIG_BBRAM_EMUL=y
21 changes: 21 additions & 0 deletions tests/subsys/boot_info/boards/qemu_x86.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright (c) 2023 Laczen
* SPDX-License-Identifier: Apache-2.0
*/

/ {
bbram_emu: bbram_emu {
compatible = "zephyr,bbram-emul";
size = <0x20>;
};

boot_info: boot_info {
compatible = "zephyr,boot-info-bbram";
backend = <&bbram_emu>;
};

aliases {
bi = &boot_info;
};

};
Loading

0 comments on commit 1715133

Please sign in to comment.