This commit adds support for CBMEM in sysfs. Useful for systems without access to /dev/mem e.g. Android. Linux kernel driver: drivers/firmware/google/cbmem.c Linux driver Kconfig: CONFIG_GOOGLE_CBMEM BUG=b:391874512 TEST=(devmem) cbmem -l; cbmem -x; cbmem -r 434f4e53; cbmem -t; cbmem -a 1200 TEST=modprobe cbmem; cbmem -l; cbmem -x; cbmem -r 434f4e53; cbmem -t; cbmem -a 1200 Change-Id: I527889509ffc84203be42d0160e5363c60eafd02 Signed-off-by: Jakub Czapiga <czapiga@google.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/86606 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Julius Werner <jwerner@chromium.org>
194 lines
6.1 KiB
C
194 lines
6.1 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
|
|
#include <inttypes.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
|
|
#include <commonlib/bsd/cbmem_id.h>
|
|
#include <commonlib/bsd/helpers.h>
|
|
|
|
extern int cbmem_util_verbose;
|
|
|
|
#define debug(x...) \
|
|
do { \
|
|
if (cbmem_util_verbose > 1) \
|
|
printf("[%s:%d %s()] ", __FILE__, __LINE__, __func__); \
|
|
if (cbmem_util_verbose) \
|
|
printf(x); \
|
|
} while (0)
|
|
|
|
#define die(x...) \
|
|
do { \
|
|
fprintf(stderr, x); \
|
|
abort(); \
|
|
} while (0)
|
|
|
|
struct cbmem_console {
|
|
uint32_t size;
|
|
uint32_t cursor;
|
|
uint8_t body[];
|
|
} __packed;
|
|
|
|
#define CBMC_CURSOR_MASK ((1 << 28) - 1)
|
|
#define CBMC_OVERFLOW (1 << 31)
|
|
|
|
/**
|
|
* Function pointer type used by CBMEM foreach iteration calls.
|
|
*
|
|
* @param id CBMEM_ID_* value.
|
|
* @param physical_address CBMEM entry address in physical memory.
|
|
* @param buf heap-allocated buffer with CBMEM entry contents.
|
|
* @param size is the size of CBMEM entry in bytes.
|
|
* @param data callback-specific context data.
|
|
*
|
|
* @returns true if iteration should finish, false if it should continue.
|
|
*/
|
|
typedef bool (*cbmem_iterator_callback)(const uint32_t id, const uint64_t physical_address,
|
|
const uint8_t *buf, const size_t size, void *data);
|
|
|
|
/* Common CBMEM access API */
|
|
|
|
enum cbmem_drv_backend_type {
|
|
CBMEM_DRV_BACKEND_ANY,
|
|
CBMEM_DRV_BACKEND_DEVMEM,
|
|
CBMEM_DRV_BACKEND_SYSFS,
|
|
};
|
|
|
|
/**
|
|
* Pick and initialize CBMEM driver. Function can either probe for available drivers or initialize only the selected one.
|
|
*
|
|
* @param backend preferred CBMEM backend to initialize.
|
|
* @param writeable initialize CBMEM driver in writeable mode. Required by devmem driver to modify CBMEM.
|
|
*
|
|
* @returns true on success, false otherwise.
|
|
*/
|
|
bool cbmem_drv_init(enum cbmem_drv_backend_type backend, bool writeable);
|
|
|
|
/**
|
|
* Cleanup and terminate previously initialized CBMEM driver.
|
|
* **MUST** be called if cbmem_drv_init() succeeded.
|
|
*/
|
|
void cbmem_drv_terminate(void);
|
|
|
|
/**
|
|
* Get CBMEM entry as an allocated buffer.
|
|
*
|
|
* @param id CBMEM_ID_* value.
|
|
* @param buf_out return pointer for the allocated buffer containing entry contents.
|
|
* @param size_out size of returned buffer.
|
|
* @param addr_out pointer to the output buffer for entry address in physical memory. Optional.
|
|
*
|
|
* @returns true on success, false otherwise.
|
|
*/
|
|
bool cbmem_drv_get_cbmem_entry(uint32_t id, uint8_t **buf_out, size_t *size_out, uint64_t *addr_out);
|
|
|
|
/**
|
|
* Write provided buffer contents to the CBMEM entry.
|
|
*
|
|
* @param id CBMEM_ID_* value.
|
|
* @param buf pointer to the source buffer.
|
|
* @param buf_size size of the source buffer.
|
|
*
|
|
* @returns true on success, false otherwise.
|
|
*/
|
|
bool cbmem_drv_write_cbmem_entry(uint32_t id, uint8_t *buf, size_t buf_size);
|
|
|
|
/**
|
|
* Backend-specific function iterating over CBMEM entries.
|
|
*
|
|
* @param cb user callback function to call during iteration.
|
|
* @param data pointer to the context data for the callback.
|
|
* @param with_contents tells whether the callback should get NULL (false) or copy of the entry (true).
|
|
*/
|
|
void cbmem_drv_foreach_cbmem_entry(cbmem_iterator_callback cb, void *data, bool with_contents);
|
|
|
|
/* API for accessing CBMEM via /dev/mem */
|
|
|
|
/**
|
|
* Initialize the driver.
|
|
*
|
|
* @param writeable tries to map CBMEM in R/W mode.
|
|
*
|
|
* @returns true on success, false otherwise.
|
|
*/
|
|
bool cbmem_devmem_init(bool writeable);
|
|
|
|
/**
|
|
* Cleanup and terminate the driver. **MUST** be called if cbmem_devmem_init succeeded before.
|
|
*/
|
|
void cbmem_devmem_terminate(void);
|
|
|
|
/**
|
|
* Get CBMEM entry as an allocated buffer.
|
|
*
|
|
* @param id CBMEM_ID_* value.
|
|
* @param buf_out return pointer for the allocated buffer containing entry contents.
|
|
* @param size_out size of returned buffer. Optional.
|
|
* @param addr_out pointer to the output buffer for entry address in physical memory. Optional.
|
|
*
|
|
* @returns true on success, false otherwise.
|
|
*/
|
|
bool cbmem_devmem_get_cbmem_entry(uint32_t id, uint8_t **buf_out, size_t *size_out, uint64_t *addr_out);
|
|
|
|
/**
|
|
* Write provided buffer contents to the CBMEM entry.
|
|
*
|
|
* @param id CBMEM_ID_* value.
|
|
* @param buf pointer to the source buffer.
|
|
* @param buf_size size of the source buffer.
|
|
*
|
|
* @returns true on success, false otherwise.
|
|
*/
|
|
bool cbmem_devmem_write_cbmem_entry(uint32_t id, uint8_t *buf, size_t buf_size);
|
|
|
|
/**
|
|
* Backend-specific function iterating over CBMEM entries.
|
|
*
|
|
* @param cb user callback function to call during iteration.
|
|
* @param data pointer to the context data for the callback.
|
|
* @param with_contents tells whether the callback should get NULL (false) or copy of the entry (true).
|
|
*/
|
|
void cbmem_devmem_foreach_cbmem_entry(cbmem_iterator_callback cb, void *data,
|
|
bool with_contents);
|
|
|
|
/* API for accessing CBMEM via sysfs entries */
|
|
|
|
/**
|
|
* Initialize the sysfs driver.
|
|
*
|
|
* @returns true on success, false otherwise.
|
|
*/
|
|
bool cbmem_sysfs_init(void);
|
|
|
|
/**
|
|
* Get CBMEM entry as an allocated buffer.
|
|
*
|
|
* @param id CBMEM_ID_* value.
|
|
* @param buf_out return pointer for the allocated buffer containing entry contents.
|
|
* @param size_out size of returned buffer.
|
|
* @param addr_out pointer to the output buffer for entry address in physical memory. Optional.
|
|
*
|
|
* @returns true on success, false otherwise.
|
|
*/
|
|
bool cbmem_sysfs_get_cbmem_entry(uint32_t id, uint8_t **buf_out, size_t *size_out, uint64_t *addr_out);
|
|
|
|
/**
|
|
* Write provided buffer contents to the CBMEM entry.
|
|
*
|
|
* @param id CBMEM_ID_* value.
|
|
* @param buf pointer to the source buffer.
|
|
* @param buf_size size of the source buffer.
|
|
*
|
|
* @returns true on success, false otherwise.
|
|
*/
|
|
bool cbmem_sysfs_write_cbmem_entry(uint32_t id, uint8_t *buf, size_t buf_size);
|
|
|
|
/**
|
|
* Backend-specific function iterating over CBMEM entries.
|
|
*
|
|
* @param cb user callback function to call during iteration.
|
|
* @param data pointer to the context data for the callback.
|
|
* @param with_contents tells whether the callback should get NULL (false) or copy of the entry (true).
|
|
*/
|
|
void cbmem_sysfs_foreach_cbmem_entry(cbmem_iterator_callback cb, void *data,
|
|
bool with_contents);
|